<script setup>
import HeroSection from "@/components/HeroSection.vue";
import ReusableDataTable from "@/components/ReusableDataTable.vue";
import ReusableDialog from "@/components/ReusableDialog.vue";
import SearchBox from "@/components/SearchBox.vue";
import { fetchStripeDashboardLink } from "@/api/paymentApi";
import { usePaymentStore } from "@/stores/paymentStore";
import { useSettingStore } from "@/stores/settingStore";
import { useToast } from "primevue/usetoast";
import { storeToRefs } from "pinia";
import Select from "primevue/select";
import { computed, onMounted, ref } from "vue";

const paymentStore = usePaymentStore();
const settingStore = useSettingStore();
const toast = useToast();
const { payments, total, loading } = storeToRefs(paymentStore);

const openingStripeDashboard = ref(false);

const hasStripeConnected = computed(() => {
  const stripe = settingStore.setting?.payment_gateway_configuration?.stripe;
  return Boolean(stripe?.stripe_account_id);
});

const lazyParams = ref({
  page: 1,
  rows: 10,
  sortField: "created_at",
  sortOrder: -1,
  search: "",
  status: "",
  paymentType: "",
});

const selectedPayment = ref(null);
const showDetailDialog = ref(false);

const statusOptions = [
  { label: "All Statuses", value: "" },
  { label: "Pending", value: "pending" },
  { label: "Succeeded", value: "succeeded" },
  { label: "Failed", value: "failed" },
  { label: "Refunded", value: "refunded" },
  { label: "Cancelled", value: "cancelled" },
];

const paymentTypeOptions = [
  { label: "All Methods", value: "" },
  { label: "Stripe", value: "stripe" },
  { label: "Viva", value: "viva" },
  { label: "Revolut", value: "revolut" },
];

const formatAmount = (rowData) => {
  const amt = Number(rowData.amount || 0).toFixed(2);
  const cur = (rowData.currency || "").toUpperCase();
  return `${cur} ${amt}`;
};

const statusBadgeClass = (status) => {
  switch ((status || "").toLowerCase()) {
    case "succeeded":
      return "pay-badge pay-badge-success";
    case "pending":
      return "pay-badge pay-badge-warning";
    case "failed":
      return "pay-badge pay-badge-danger";
    case "refunded":
      return "pay-badge pay-badge-info";
    case "cancelled":
      return "pay-badge pay-badge-muted";
    default:
      return "pay-badge pay-badge-muted";
  }
};

const columns = [
  {
    field: "amount",
    header: "Amount",
    sortable: true,
    style: { minWidth: "140px" },
    template: "custom",
    customHTML: (rowData) =>
      `<span class="text-sm font-semibold text-slate-800">${formatAmount(rowData)}</span>`,
  },
  {
    field: "payment_type",
    header: "Method",
    sortable: true,
    style: { minWidth: "120px" },
    template: "custom",
    customHTML: (rowData) => {
      const pt = (rowData.payment_type || "").toLowerCase();
      const label = pt ? pt.charAt(0).toUpperCase() + pt.slice(1) : "—";
      return `<span class="pay-method pay-method-${pt || "other"}">${label}</span>`;
    },
  },
  {
    field: "status",
    header: "Status",
    sortable: true,
    style: { minWidth: "120px" },
    template: "custom",
    customHTML: (rowData) =>
      `<span class="${statusBadgeClass(rowData.status)}">${rowData.status || "—"}</span>`,
  },
  {
    field: "created_at",
    header: "Date",
    sortable: true,
    type: "datetime",
    style: { minWidth: "160px" },
  },
];

const actions = [
  {
    icon: "pi pi-eye",
    tooltip: "View Payment",
    severity: "info",
    action: "view",
  },
];

const loadPayments = async () => {
  await paymentStore.fetchPaymentsLazy(lazyParams.value);
};

const onPage = (event) => {
  lazyParams.value.page = event.page + 1;
  lazyParams.value.rows = event.rows;
  loadPayments();
};

const onSort = (event) => {
  lazyParams.value.sortField = event.sortField;
  lazyParams.value.sortOrder = event.sortOrder;
  loadPayments();
};

const handleSearch = (term) => {
  lazyParams.value.search = term;
  lazyParams.value.page = 1;
  loadPayments();
};

const handleClearSearch = () => {
  lazyParams.value.search = "";
  lazyParams.value.page = 1;
  loadPayments();
};

const onFilterChange = () => {
  lazyParams.value.page = 1;
  paymentStore.clearCache();
  loadPayments();
};

const onActionClick = ({ action, rowData }) => {
  if (action.action === "view") {
    selectedPayment.value = rowData;
    showDetailDialog.value = true;
  }
};

const copyToClipboard = (val) => {
  if (!val) return;
  try {
    navigator.clipboard?.writeText(val);
  } catch (_) {
    // best effort only
  }
};

const formatDate = (val) => {
  if (!val) return "—";
  try {
    return new Date(val).toLocaleString();
  } catch (_) {
    return val;
  }
};

const hasCustomerInfo = (payment) => {
  if (!payment) return false;
  return Boolean(
    payment.user_email ||
      payment.registration_id ||
      payment.registrant?.name ||
      payment.registrant?.email ||
      payment.registrant?.parent ||
      payment.registrant?.phone,
  );
};

const openStripeDashboard = async () => {
  openingStripeDashboard.value = true;
  try {
    const response = await fetchStripeDashboardLink();
    const payload = response?.data?.data;
    const url = payload?.url;
    if (!url) {
      toast.add({
        severity: "error",
        summary: "Stripe Dashboard",
        detail: response?.data?.message || "Could not create dashboard link.",
        life: 5000,
      });
      return;
    }
    window.open(url, "_blank", "noopener,noreferrer");
    toast.add({
      severity: payload?.requires_stripe_login ? "info" : "success",
      summary: "Stripe Dashboard",
      detail:
        response?.data?.message ||
        "Opening your Stripe Dashboard in a new tab.",
      life: payload?.requires_stripe_login ? 8000 : 5000,
    });
  } catch (error) {
    const detail =
      error?.response?.data?.message ||
      error?.message ||
      "Failed to open Stripe Dashboard.";
    toast.add({
      severity: "error",
      summary: "Stripe Dashboard",
      detail,
      life: 6000,
    });
  } finally {
    openingStripeDashboard.value = false;
  }
};

onMounted(async () => {
  if (!settingStore.setting) {
    try {
      await settingStore.getSetting();
    } catch (_) {
      // Payments list still works without settings
    }
  }
  loadPayments();
});
</script>

<template>
  <div class="payments-page-container">
    <HeroSection
      title="Payments"
      subtitle="View your franchise payment history"
      icon="pi pi-credit-card"
    />

    <div class="content-wrapper">
      <div class="page-content">
        <div class="toolbar">
          <div class="toolbar-left">
            <div class="search-section">
              <SearchBox
                v-model="lazyParams.search"
                placeholder="Search by status, amount…"
                :loading="loading"
                @search="handleSearch"
                @clear="handleClearSearch"
                class="w-full"
              />
            </div>
          </div>

          <div class="toolbar-actions">
            <button
              v-if="hasStripeConnected"
              type="button"
              class="stripe-dashboard-btn"
              :disabled="openingStripeDashboard || loading"
              @click="openStripeDashboard"
            >
              <i
                class="pi"
                :class="openingStripeDashboard ? 'pi-spin pi-spinner' : 'pi-external-link'"
              />
              <span>Open Stripe Dashboard</span>
            </button>
          </div>

          <div class="filters">
            <Select
              v-model="lazyParams.status"
              :options="statusOptions"
              option-label="label"
              option-value="value"
              placeholder="Status"
              class="filter-control"
              @change="onFilterChange"
            />
            <Select
              v-model="lazyParams.paymentType"
              :options="paymentTypeOptions"
              option-label="label"
              option-value="value"
              placeholder="Method"
              class="filter-control"
              @change="onFilterChange"
            />
          </div>
        </div>

        <div class="table-container">
          <ReusableDataTable
            :data="payments"
            :columns="columns"
            :actions="actions"
            :loading="loading"
            :total-records="total"
            :rows="lazyParams.rows"
            :sort-field="lazyParams.sortField"
            :sort-order="lazyParams.sortOrder"
            :lazy="true"
            :paginator="true"
            :rows-per-page-options="[10, 25, 50, 100]"
            data-key="id"
            @page="onPage"
            @sort="onSort"
            @action-click="onActionClick"
          />
        </div>
      </div>
    </div>

    <ReusableDialog
      v-model="showDetailDialog"
      title="Payment Details"
      :max-width="560"
    >
      <template #default>
        <div v-if="selectedPayment" class="payment-detail">
          <!-- Hero amount block -->
          <div class="amount-hero">
            <div class="amount-hero-left">
              <span class="amount-label">Amount</span>
              <div class="amount-value">{{ formatAmount(selectedPayment) }}</div>
              <span class="amount-date">
                {{ formatDate(selectedPayment.created_at) }}
              </span>
            </div>
            <span :class="['status-chip', statusBadgeClass(selectedPayment.status)]">
              {{ selectedPayment.status || "—" }}
            </span>
          </div>

          <!-- Payment section -->
          <div class="info-section">
            <div class="info-section-title">Payment</div>

            <div class="info-grid">
              <div class="info-cell">
                <span class="info-key">Method</span>
                <span class="info-val">
                  <span
                    :class="['method-chip', `pay-method-${(selectedPayment.payment_type || 'other').toLowerCase()}`]"
                  >
                    {{ (selectedPayment.payment_type || "—").toUpperCase() }}
                  </span>
                </span>
              </div>
              <div class="info-cell">
                <span class="info-key">Currency</span>
                <span class="info-val">
                  {{ (selectedPayment.currency || "—").toUpperCase() }}
                </span>
              </div>
              <div class="info-cell">
                <span class="info-key">Updated</span>
                <span class="info-val">
                  {{ formatDate(selectedPayment.updated_at) }}
                </span>
              </div>
              <div
                v-if="selectedPayment.transaction_id"
                class="info-cell"
              >
                <span class="info-key">Transaction ID</span>
                <span class="info-val mono">
                  {{ selectedPayment.transaction_id }}
                </span>
              </div>
            </div>

            <div v-if="selectedPayment.payment_intent_id" class="info-stacked">
              <span class="info-key">Payment Intent ID</span>
              <div class="info-mono-row">
                <code class="mono-pill">{{ selectedPayment.payment_intent_id }}</code>
                <button
                  class="copy-btn"
                  title="Copy"
                  @click="copyToClipboard(selectedPayment.payment_intent_id)"
                >
                  <i class="pi pi-copy"></i>
                </button>
              </div>
            </div>
          </div>

          <!-- Customer section -->
          <div
            v-if="hasCustomerInfo(selectedPayment)"
            class="info-section"
          >
            <div class="info-section-title">Customer</div>

            <div class="info-grid">
              <div
                v-if="selectedPayment.registrant?.name"
                class="info-cell"
              >
                <span class="info-key">Name</span>
                <span class="info-val">{{ selectedPayment.registrant.name }}</span>
              </div>
              <div
                v-if="selectedPayment.user_email || selectedPayment.registrant?.email"
                class="info-cell info-cell-wide"
              >
                <span class="info-key">Email</span>
                <span class="info-val">
                  {{
                    selectedPayment.user_email ||
                    selectedPayment.registrant?.email
                  }}
                </span>
              </div>
              <div
                v-if="selectedPayment.registrant?.parent"
                class="info-cell"
              >
                <span class="info-key">Parent</span>
                <span class="info-val">{{ selectedPayment.registrant.parent }}</span>
              </div>
              <div
                v-if="selectedPayment.registrant?.phone"
                class="info-cell"
              >
                <span class="info-key">Phone</span>
                <span class="info-val">{{ selectedPayment.registrant.phone }}</span>
              </div>
            </div>

            <div v-if="selectedPayment.registration_id" class="info-stacked">
              <span class="info-key">Registration ID</span>
              <div class="info-mono-row">
                <code class="mono-pill">{{ selectedPayment.registration_id }}</code>
                <button
                  class="copy-btn"
                  title="Copy"
                  @click="copyToClipboard(selectedPayment.registration_id)"
                >
                  <i class="pi pi-copy"></i>
                </button>
              </div>
            </div>
          </div>
        </div>
      </template>
    </ReusableDialog>
  </div>
</template>

<style scoped>
.content-wrapper {
  max-width: 1400px;
  margin: 0 auto;
  padding: 0 1.5rem;
  position: relative;
  z-index: 10;
}

.page-content {
  background: transparent;
}

.toolbar {
  background: white;
  padding: 1.25rem 1.5rem;
  border-radius: 12px 12px 0 0;
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 1rem;
  flex-wrap: wrap;
  border: 1px solid #e2e8f0;
  border-bottom: none;
}

.toolbar-left {
  display: flex;
  align-items: center;
  gap: 1rem;
  flex: 1;
  min-width: 240px;
}

.search-section {
  flex: 1;
  max-width: 400px;
}

.toolbar-actions {
  display: flex;
  align-items: center;
  flex-shrink: 0;
}

.stripe-dashboard-btn {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.55rem 1rem;
  border-radius: 8px;
  border: 1px solid #635bff;
  background: #635bff;
  color: #fff;
  font-size: 0.875rem;
  font-weight: 600;
  cursor: pointer;
  transition: background 0.2s ease, opacity 0.2s ease;
  white-space: nowrap;
}

.stripe-dashboard-btn:hover:not(:disabled) {
  background: #4f46e5;
  border-color: #4f46e5;
}

.stripe-dashboard-btn:disabled {
  opacity: 0.6;
  cursor: not-allowed;
}

.filters {
  display: flex;
  gap: 0.75rem;
  flex-wrap: wrap;
}

.filter-control {
  min-width: 180px;
}

:deep(.reusable-data-table-container) {
  border-top-left-radius: 0 !important;
  border-top-right-radius: 0 !important;
  border-top: none !important;
}

/* ============================
   PAYMENT DETAIL DIALOG
============================ */
.payment-detail {
  padding: 1.5rem 1.75rem 1.75rem;
  display: flex;
  flex-direction: column;
  gap: 1.5rem;
}

/* Hero amount block */
.amount-hero {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 1rem;
  padding-bottom: 1.25rem;
  border-bottom: 1px solid #eef2f7;
}

.amount-hero-left {
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
  min-width: 0;
}

.amount-label {
  font-size: 0.7rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: #94a3b8;
}

.amount-value {
  font-size: 1.875rem;
  font-weight: 700;
  color: #0f172a;
  line-height: 1.15;
  letter-spacing: -0.01em;
}

.amount-date {
  font-size: 0.78rem;
  color: #64748b;
}

.status-chip {
  flex-shrink: 0;
  align-self: flex-start;
}

/* Sections */
.info-section {
  display: flex;
  flex-direction: column;
  gap: 0.9rem;
}

.info-section-title {
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: #94a3b8;
  position: relative;
  padding-bottom: 0.4rem;
  border-bottom: 1px solid #f1f5f9;
}

/* Two-column key/value grid */
.info-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0.85rem 1.5rem;
}

.info-cell {
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
  min-width: 0;
}

.info-cell-wide {
  grid-column: 1 / -1;
}

.info-key {
  font-size: 0.7rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: #94a3b8;
}

.info-val {
  font-size: 0.9rem;
  font-weight: 600;
  color: #1e293b;
  word-break: break-word;
}

.info-val.mono {
  font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
  font-size: 0.8rem;
  font-weight: 500;
}

/* Stacked rows for long IDs */
.info-stacked {
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
}

.info-mono-row {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

.mono-pill {
  flex: 1;
  font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
  font-size: 0.78rem;
  background: #f8fafc;
  color: #1e293b;
  padding: 0.5rem 0.75rem;
  border-radius: 8px;
  border: 1px solid #e2e8f0;
  word-break: break-all;
  line-height: 1.4;
}

.copy-btn {
  background: #f1f5f9;
  border: 1px solid #e2e8f0;
  width: 32px;
  height: 32px;
  border-radius: 8px;
  color: #475569;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  transition: all 0.18s ease;
}

.copy-btn:hover {
  background: #003b6f;
  border-color: #003b6f;
  color: white;
}

.method-chip {
  display: inline-block;
  padding: 0.15rem 0.55rem;
  border-radius: 6px;
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  background: #eef2ff;
  color: #3730a3;
  border: 1px solid #c7d2fe;
}

@media (max-width: 768px) {
  .content-wrapper {
    padding: 0 1rem;
  }
  .toolbar {
    flex-direction: column;
    align-items: stretch;
  }
  .filters {
    width: 100%;
  }
  .filter-control {
    flex: 1;
    min-width: 0;
  }
  .payment-detail {
    padding: 1.25rem 1.25rem 1.5rem;
  }
  .info-grid {
    grid-template-columns: 1fr;
  }
  .amount-value {
    font-size: 1.6rem;
  }
}
</style>

<style>
.pay-badge {
  padding: 0.2rem 0.65rem;
  border-radius: 999px;
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.02em;
  text-transform: capitalize;
  display: inline-block;
}

.pay-badge-success {
  background-color: #dcfce7;
  color: #15803d;
  border: 1px solid #bbf7d0;
}

.pay-badge-warning {
  background-color: #fef3c7;
  color: #b45309;
  border: 1px solid #fde68a;
}

.pay-badge-danger {
  background-color: #fee2e2;
  color: #b91c1c;
  border: 1px solid #fecaca;
}

.pay-badge-info {
  background-color: #e0f2fe;
  color: #0369a1;
  border: 1px solid #bae6fd;
}

.pay-badge-muted {
  background-color: #f1f5f9;
  color: #475569;
  border: 1px solid #e2e8f0;
}

.pay-method {
  padding: 0.18rem 0.55rem;
  border-radius: 6px;
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.02em;
  background: #eef2ff;
  color: #3730a3;
  border: 1px solid #c7d2fe;
}

.pay-method-stripe {
  background: #ede9fe;
  color: #5b21b6;
  border-color: #ddd6fe;
}

.pay-method-viva {
  background: #ecfeff;
  color: #0e7490;
  border-color: #cffafe;
}

.pay-method-revolut {
  background: #fdf2f8;
  color: #be185d;
  border-color: #fbcfe8;
}
</style>
