<template>
  <div class="tx-history">
    <h3 class="tx-history__title">
      Transaction History
      <span class="tx-history__count" v-if="transactions.length">{{ transactions.length }}</span>
    </h3>

    <div v-if="loading" class="tx-history__loading">
      <div class="spinner"></div>
      Loading transactions…
    </div>

    <div v-else-if="transactions.length === 0" class="tx-history__empty">No transactions found for this address.</div>

    <div v-else class="tx-history__table-wrapper">
      <table class="tx-table">
        <thead>
          <tr>
            <th>Date</th>
            <th>Type</th>
            <th class="text-right">Amount (KRK)</th>
            <th class="text-right">Value (ETH)</th>
            <th>Tx</th>
          </tr>
        </thead>
        <tbody>
          <tr v-for="tx in transactions" :key="tx.id" :class="txRowClass(tx.type)">
            <td class="tx-date">{{ formatDate(tx.timestamp) }}</td>
            <td>
              <span class="tx-type-badge" :class="txTypeClass(tx.type)">
                {{ txTypeLabel(tx.type) }}
              </span>
            </td>
            <td class="text-right mono">{{ formatKrk(tx.tokenAmount) }}</td>
            <td class="text-right mono">{{ tx.ethAmount !== '0' ? formatEth(tx.ethAmount) : '—' }}</td>
            <td>
              <a :href="explorerTxUrl(tx.txHash)" target="_blank" rel="noopener noreferrer" class="tx-link" :title="tx.txHash">
                {{ shortHash(tx.txHash) }} ↗
              </a>
            </td>
          </tr>
        </tbody>
      </table>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, watch, onMounted } from 'vue';

interface Transaction {
  id: string;
  holder: string;
  type: string;
  tokenAmount: string;
  ethAmount: string;
  timestamp: string;
  blockNumber: number;
  txHash: string;
}

const props = defineProps<{
  address: string;
  graphqlUrl?: string;
}>();

const transactions = ref<Transaction[]>([]);
const loading = ref(true);

const GRAPHQL_URL = props.graphqlUrl || '/api/graphql';

async function fetchTransactions(address: string) {
  if (!address) {
    loading.value = false;
    return;
  }
  loading.value = true;

  try {
    const query = `{
      transactionss(
        where: { holder: "${address.toLowerCase()}" }
        orderBy: "timestamp"
        orderDirection: "desc"
        limit: 50
      ) {
        items {
          id
          holder
          type
          tokenAmount
          ethAmount
          timestamp
          blockNumber
          txHash
        }
      }
    }`;

    const res = await fetch(GRAPHQL_URL, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ query }),
    });

    const data = await res.json();
    transactions.value = data?.data?.transactionss?.items ?? [];
  } catch (e) {
    // eslint-disable-next-line no-console
    console.error('Failed to fetch transactions:', e);
    transactions.value = [];
  } finally {
    loading.value = false;
  }
}

function formatDate(timestamp: string): string {
  const ts = Number(timestamp) * 1000;
  if (!ts) return '—';
  const d = new Date(ts);
  return (
    d.toLocaleDateString('en-US', { month: 'short', day: 'numeric', year: '2-digit' }) +
    ' ' +
    d.toLocaleTimeString('en-US', { hour: '2-digit', minute: '2-digit', hour12: false })
  );
}

function formatKrk(raw: string): string {
  try {
    const val = Number(BigInt(raw || '0')) / 1e18;
    return val.toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 4 });
  } catch {
    return '0.00';
  }
}

function formatEth(raw: string): string {
  try {
    const val = Number(BigInt(raw || '0')) / 1e18;
    return val.toLocaleString('en-US', { minimumFractionDigits: 4, maximumFractionDigits: 6 });
  } catch {
    return '0.0000';
  }
}

function shortHash(hash: string): string {
  if (!hash || hash.length < 12) return hash;
  return `${hash.slice(0, 6)}…${hash.slice(-4)}`;
}

function explorerTxUrl(hash: string): string {
  // Base mainnet explorer; adjust for testnet if needed
  return `https://basescan.org/tx/${hash}`;
}

function txTypeLabel(type: string): string {
  const labels: Record<string, string> = {
    buy: 'Buy',
    sell: 'Sell',
    stake: 'Stake',
    unstake: 'Unstake',
    snatch_in: 'Snatched In',
    snatch_out: 'Snatched Out',
  };
  return labels[type] || type;
}

function txTypeClass(type: string): string {
  if (['buy', 'unstake', 'snatch_in'].includes(type)) return 'tx-type--positive';
  if (['sell', 'snatch_out'].includes(type)) return 'tx-type--negative';
  return 'tx-type--neutral';
}

function txRowClass(type: string): string {
  if (['buy', 'unstake'].includes(type)) return 'tx-row--positive';
  if (['sell', 'snatch_out'].includes(type)) return 'tx-row--negative';
  return '';
}

onMounted(() => fetchTransactions(props.address));
watch(
  () => props.address,
  addr => fetchTransactions(addr)
);
</script>

<style lang="sass" scoped>
.tx-history
  display: flex
  flex-direction: column
  gap: 16px

  &__title
    display: flex
    align-items: center
    gap: 10px
    font-size: 20px
    color: #ffffff
    margin: 0

  &__count
    background: rgba(117, 80, 174, 0.3)
    color: #7550AE
    border-radius: 99px
    padding: 2px 10px
    font-size: 14px
    font-weight: 700

  &__loading
    display: flex
    align-items: center
    gap: 12px
    color: #9A9898
    padding: 24px

  &__empty
    color: #9A9898
    padding: 24px
    text-align: center
    background: #07111B
    border-radius: 12px
    border: 1px solid rgba(255,255,255,0.07)

  &__table-wrapper
    overflow-x: auto
    border-radius: 12px
    border: 1px solid rgba(255,255,255,0.08)

.tx-table
  width: 100%
  border-collapse: collapse
  font-size: 14px

  th
    text-align: left
    padding: 12px 16px
    color: #9A9898
    font-size: 11px
    text-transform: uppercase
    letter-spacing: 1px
    border-bottom: 1px solid rgba(255,255,255,0.08)
    white-space: nowrap

  td
    padding: 12px 16px
    border-bottom: 1px solid rgba(255,255,255,0.04)
    color: #ffffff

  .text-right
    text-align: right

  .mono
    font-family: monospace

.tx-date
  color: #9A9898
  white-space: nowrap
  font-size: 13px

.tx-type-badge
  padding: 3px 10px
  border-radius: 99px
  font-size: 12px
  font-weight: 600
  text-transform: uppercase
  letter-spacing: 0.5px

  &.tx-type--positive
    background: rgba(74, 222, 128, 0.12)
    color: #4ADE80

  &.tx-type--negative
    background: rgba(248, 113, 113, 0.12)
    color: #F87171

  &.tx-type--neutral
    background: rgba(117, 80, 174, 0.15)
    color: #7550AE

.tx-row--positive td
  background: rgba(74, 222, 128, 0.03)

.tx-row--negative td
  background: rgba(248, 113, 113, 0.03)

.tx-link
  color: #7550AE
  text-decoration: none
  font-family: monospace
  font-size: 13px
  white-space: nowrap
  &:hover
    text-decoration: underline

.spinner
  width: 20px
  height: 20px
  border: 2px solid rgba(117, 80, 174, 0.3)
  border-top-color: #7550AE
  border-radius: 50%
  animation: spin 0.8s linear infinite

@keyframes spin
  to
    transform: rotate(360deg)
</style>
