'use client';

import React, { useState, useEffect } from 'react';
import Link from 'next/link';
import { formatCurrency } from '@/lib/utils';
import { ErrorState } from '@/components/ui/ErrorState';
import {
  ArrowLeft,
  CheckCircle2,
  AlertTriangle,
  Loader2,
  RefreshCcw,
  ArrowRightLeft,
  Search,
  Check,
  Zap,
  Download,
  Flag,
} from 'lucide-react';
import { apiFetch, apiJson, ApiError } from '@/lib/api-client';
import { toast } from '@/lib/toast';
import { confirmDialog } from '@/lib/confirm';


interface BankTransaction {
  id: string;
  bankAccountId: string;
  bankAccountName: string;
  bankAccountMasked: string;
  transactionDate: string;
  description: string;
  amount: number;
  transactionType: string;
  referenceNumber: string | null;
  oppositeParty: string | null;
  reconciled: boolean;
  reconciledAt: string | null;
  status: string;
}

interface BankAccount {
  id: string;
  accountName: string;
  bankName: string;
  currentBalance: number;
  accountNumberMasked: string;
}

export default function ReconciliationPage() {
  const [accounts, setAccounts] = useState<BankAccount[]>([]);
  const [transactions, setTransactions] = useState<BankTransaction[]>([]);
  const [selectedAccount, setSelectedAccount] = useState<string>('all');
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);
  const [search, setSearch] = useState('');
  const [selectedIds, setSelectedIds] = useState<Set<string>>(new Set());
  const [reconciling, setReconciling] = useState(false);
  const [showReconciled, setShowReconciled] = useState(false);
  const [autoMatching, setAutoMatching] = useState(false);
  const [completing, setCompleting] = useState(false);

  useEffect(() => {
    fetchData();
  }, []);

  const fetchData = async () => {
    setLoading(true);
    setError(null);
    const controller = new AbortController();
    const timeoutId = setTimeout(() => controller.abort(), 30000);
    try {
      const [acctsData, txnsData] = await Promise.all([
        apiJson<any>('/api/bank-accounts', { signal: controller.signal, cache: 'no-store', silent: true }),
        apiJson<any>('/api/bank-transactions', { signal: controller.signal, cache: 'no-store', silent: true }),
      ]);
      setAccounts(Array.isArray(acctsData) ? acctsData : acctsData.accounts || []);
      setTransactions(Array.isArray(txnsData) ? txnsData : txnsData.transactions || []);
    } catch (err: any) {
      const msg =
        err?.name === 'AbortError'
          ? 'Request timed out after 30s'
          : err instanceof ApiError
            ? err.message
            : err?.message || 'Failed to fetch reconciliation data';
      console.error('[Reconciliation] fetch error:', err);
      setError(msg);
    } finally {
      clearTimeout(timeoutId);
      setLoading(false);
    }
  };

  const filteredTransactions = transactions.filter((txn) => {
    if (selectedAccount !== 'all' && txn.bankAccountId !== selectedAccount) return false;
    if (!showReconciled && txn.reconciled) return false;
    if (search.trim()) {
      const q = search.toLowerCase();
      return (
        txn.description?.toLowerCase().includes(q) ||
        txn.referenceNumber?.toLowerCase().includes(q) ||
        String(txn.amount).includes(q)
      );
    }
    return true;
  });

  const unreconciledCount = transactions.filter((t) => !t.reconciled).length;
  const reconciledCount = transactions.filter((t) => t.reconciled).length;
  const selectedTotal = filteredTransactions
    .filter((t) => selectedIds.has(t.id))
    .reduce((sum, t) => sum + Number(t.amount), 0);

  const toggleSelect = (id: string) => {
    setSelectedIds((prev) => {
      const next = new Set(prev);
      if (next.has(id)) next.delete(id);
      else next.add(id);
      return next;
    });
  };

  const selectAll = () => {
    const unreconciled = filteredTransactions.filter((t) => !t.reconciled);
    if (selectedIds.size === unreconciled.length) {
      setSelectedIds(new Set());
    } else {
      setSelectedIds(new Set(unreconciled.map((t) => t.id)));
    }
  };

  const handleReconcile = async () => {
    if (selectedIds.size === 0) return;
    setReconciling(true);
    try {
      // Mark selected transactions as reconciled
      await apiFetch('/api/bank-transactions/reconcile', {
        method: 'POST',
        body: JSON.stringify({ transactionIds: Array.from(selectedIds) }),
        silent: true,
      });

      // Update local state
      setTransactions((prev) =>
        prev.map((t) =>
          selectedIds.has(t.id) ? { ...t, reconciled: true, reconciledAt: new Date().toISOString() } : t
        )
      );
      setSelectedIds(new Set());
    } catch (err) {
      toast.error('Failed to reconcile transactions. Please try again.');
    } finally {
      setReconciling(false);
    }
  };

  const handleAutoMatch = async () => {
    if (transactions.length === 0) return;
    setAutoMatching(true);
    try {
      const data = await apiJson<any>('/api/bank-transactions/auto-match', {
        method: 'POST',
        body: JSON.stringify({
          bankAccountId: selectedAccount !== 'all' ? selectedAccount : undefined,
        }),
        silent: true,
      });
      const matchedIds = new Set<string>((data.matches || []).map((m: any) => m.txnId));

      if (matchedIds.size > 0) {
        setTransactions((prev) =>
          prev.map((t) =>
            matchedIds.has(t.id) ? { ...t, reconciled: true, reconciledAt: new Date().toISOString() } : t
          )
        );
        toast.success(`Auto-matched ${matchedIds.size} transaction(s) against payments and journal entries`);
      } else {
        toast.success('No matches found. Try widening the date window or importing more payments.');
      }
    } catch (err: any) {
      toast.error(err instanceof ApiError ? err.message : (err?.message || 'Failed to auto-match. Please try again.'));
    } finally {
      setAutoMatching(false);
    }
  };

  const handleExportReconciliation = () => {
    try {
      const csv = generateReconciliationCSV();
      const blob = new Blob([csv], { type: 'text/csv;charset=utf-8;' });
      const link = document.createElement('a');
      const url = URL.createObjectURL(blob);
      link.setAttribute('href', url);
      link.setAttribute('download', `reconciliation-${new Date().toISOString().split('T')[0]}.csv`);
      link.click();
    } catch (err) {
      toast.error('Failed to export reconciliation');
    }
  };

  const generateReconciliationCSV = () => {
    const lines = [
      ['Bank Reconciliation Report'],
      [`Generated: ${new Date().toLocaleString()}`],
      [''],
      ['Date', 'Account', 'Description', 'Amount', 'Status', 'Reconciled At'],
      ...transactions.map((t) => [
        new Date(t.transactionDate).toLocaleDateString(),
        t.bankAccountName,
        t.description,
        t.amount.toString(),
        t.reconciled ? 'Reconciled' : 'Unreconciled',
        t.reconciledAt ? new Date(t.reconciledAt).toLocaleString() : '—',
      ]),
      [''],
      ['Summary'],
      ['Total Unreconciled', transactions.filter((t) => !t.reconciled).length.toString()],
      ['Total Reconciled', transactions.filter((t) => t.reconciled).length.toString()],
      ['Reconciliation Rate', `${Math.round((transactions.filter((t) => t.reconciled).length / transactions.length) * 100)}%`],
    ];
    return lines.map((row) => row.map((cell) => `"${cell}"`).join(',')).join('\n');
  };

  const handleCompleteReconciliation = async () => {
    const unreconciledCount = transactions.filter((t) => !t.reconciled).length;
    if (unreconciledCount > 0) {
      if (!await confirmDialog(`${unreconciledCount} transaction(s) are still unreconciled. Complete anyway?`)) {
        return;
      }
    }

    if (selectedAccount === 'all') {
      toast.error('Select a specific bank account before completing a reconciliation period.');
      return;
    }

    const stmtRaw = window.prompt('Enter the ending statement balance from your bank statement:', '0.00');
    if (stmtRaw === null) return;
    const stmtBalance = parseFloat(stmtRaw);
    if (Number.isNaN(stmtBalance)) {
      toast.error('Invalid statement balance');
      return;
    }

    setCompleting(true);
    try {
      try {
        await apiFetch('/api/reconciliation/complete', {
          method: 'POST',
          body: JSON.stringify({
            bankAccountId: selectedAccount,
            statementBalance: stmtBalance,
          }),
          silent: true,
        });
      } catch (err) {
        if (err instanceof ApiError) {
          const body = err.body as { difference?: number; error?: string } | null;
          // If out-of-balance, let the user retry with force
          if (body && typeof body.difference === 'number') {
            if (await confirmDialog(
              `Reconciliation is out of balance by $${body.difference.toFixed(2)}. Complete anyway?`
            )) {
              await apiFetch('/api/reconciliation/complete', {
                method: 'POST',
                body: JSON.stringify({
                  bankAccountId: selectedAccount,
                  statementBalance: stmtBalance,
                  force: true,
                }),
                silent: true,
              });
            } else {
              return;
            }
          } else {
            throw err;
          }
        } else {
          throw err;
        }
      }
      toast.success('Reconciliation period completed successfully');
      fetchData();
    } catch (err: any) {
      toast.error(err?.message || 'Failed to complete reconciliation. Please try again.');
    } finally {
      setCompleting(false);
    }
  };

  if (loading) {
    return (
      <div className="flex items-center justify-center min-h-[60vh]">
        <Loader2 size={32} className="text-blue-500 animate-spin" />
      </div>
    );
  }

  if (error) {
    return <ErrorState message={error} title="Couldn't load reconciliation" onRetry={fetchData} />;
  }

  return (
    <div className="space-y-6">
      {/* Header */}
      <div className="flex items-center justify-between">
        <div className="flex items-center gap-3">
          <Link href="/finance/treasury" className="p-2 hover:bg-[#222228] rounded-lg">
            <ArrowLeft size={20} className="text-[#8B8B9E]" />
          </Link>
          <div>
            <h1 className="text-2xl font-bold text-[#F0F0F3] flex items-center gap-2">
              <ArrowRightLeft size={24} className="text-blue-600" />
              Bank Reconciliation
            </h1>
            <p className="text-sm text-[#5A5A6E] mt-0.5">Match bank transactions with GL entries</p>
          </div>
        </div>
        <div className="flex items-center gap-2">
          <button
            onClick={handleAutoMatch}
            disabled={autoMatching || transactions.filter((t) => !t.reconciled).length === 0}
            className="flex items-center gap-2 px-3 py-2 text-sm bg-blue-600 text-white rounded-lg hover:bg-blue-700 disabled:opacity-50 disabled:cursor-not-allowed"
          >
            <Zap size={14} />
            {autoMatching ? 'Matching...' : 'Auto-Match'}
          </button>
          <button
            onClick={handleExportReconciliation}
            className="flex items-center gap-2 px-3 py-2 text-sm border border-[#2A2A32] rounded-lg hover:bg-[#222228]"
          >
            <Download size={14} />
            Export
          </button>
          <button
            onClick={handleCompleteReconciliation}
            disabled={completing}
            className="flex items-center gap-2 px-3 py-2 text-sm bg-emerald-600 text-white rounded-lg hover:bg-emerald-700 disabled:opacity-50"
          >
            <Flag size={14} />
            {completing ? 'Completing...' : 'Complete Period'}
          </button>
          <button
            onClick={fetchData}
            className="flex items-center gap-2 px-3 py-2 text-sm border border-[#2A2A32] rounded-lg hover:bg-[#222228]"
          >
            <RefreshCcw size={14} />
            Refresh
          </button>
        </div>
      </div>

      {/* Summary Cards */}
      <div className="grid grid-cols-1 md:grid-cols-4 gap-4">
        <div className="bg-[#1A1A1F] rounded-xl p-4 border border-[#2A2A32]">
          <p className="text-xs font-medium text-[#5A5A6E]">Total Transactions</p>
          <p className="text-2xl font-bold text-[#F0F0F3] mt-1">{transactions.length}</p>
        </div>
        <div className="bg-amber-900/20 rounded-xl p-4 border border-amber-800/40">
          <p className="text-xs font-medium text-amber-400">Unreconciled</p>
          <p className="text-2xl font-bold text-amber-300 mt-1">{unreconciledCount}</p>
        </div>
        <div className="bg-emerald-900/20 rounded-xl p-4 border border-emerald-800/40">
          <p className="text-xs font-medium text-emerald-400">Reconciled</p>
          <p className="text-2xl font-bold text-emerald-300 mt-1">{reconciledCount}</p>
        </div>
        <div className="bg-blue-900/20 rounded-xl p-4 border border-blue-800/40">
          <p className="text-xs font-medium text-blue-400">Reconciliation Rate</p>
          <p className="text-2xl font-bold text-blue-300 mt-1">
            {transactions.length > 0 ? Math.round((reconciledCount / transactions.length) * 100) : 0}%
          </p>
        </div>
      </div>

      {/* Filters & Actions */}
      <div className="bg-[#1A1A1F] rounded-xl border border-[#2A2A32] p-4">
        <div className="flex flex-wrap items-center gap-3">
          {/* Account filter */}
          <select
            value={selectedAccount}
            onChange={(e) => setSelectedAccount(e.target.value)}
            className="text-sm border border-[#2A2A32] rounded-lg px-3 py-2 bg-[#111114] outline-none focus:ring-2 focus:ring-indigo-500 text-[#F0F0F3]"
          >
            <option value="all">All Accounts</option>
            {accounts.map((acct) => (
              <option key={acct.id} value={acct.id}>
                {acct.bankName} - {acct.accountName}
              </option>
            ))}
          </select>

          {/* Search */}
          <div className="flex items-center gap-2 bg-[#222228] rounded-lg px-3 py-2 flex-1 min-w-[200px]">
            <Search size={16} className="text-[#5A5A6E]" />
            <input
              type="text"
              placeholder="Search transactions..."
              value={search}
              onChange={(e) => setSearch(e.target.value)}
              className="bg-transparent text-sm outline-none w-full"
            />
          </div>

          {/* Show reconciled toggle */}
          <label className="flex items-center gap-2 text-sm text-[#8B8B9E] cursor-pointer">
            <input
              type="checkbox"
              checked={showReconciled}
              onChange={(e) => setShowReconciled(e.target.checked)}
              className="rounded border-[#3A3A45]"
            />
            Show reconciled
          </label>

          {/* Reconcile button */}
          {selectedIds.size > 0 && (
            <button
              onClick={handleReconcile}
              disabled={reconciling}
              className="ml-auto flex items-center gap-2 px-4 py-2 bg-emerald-600 text-white text-sm rounded-lg hover:bg-emerald-700 disabled:opacity-50 font-medium"
            >
              {reconciling ? (
                <Loader2 size={14} className="animate-spin" />
              ) : (
                <Check size={14} />
              )}
              Reconcile {selectedIds.size} transaction{selectedIds.size > 1 ? 's' : ''}
              <span className="text-emerald-200">({formatCurrency(selectedTotal)})</span>
            </button>
          )}
        </div>
      </div>

      {/* Transaction Table */}
      <div className="bg-[#1A1A1F] rounded-xl border border-[#2A2A32] overflow-hidden">
        <div className="overflow-x-auto">
          <table className="w-full text-sm">
            <thead>
              <tr className="bg-[#111114] border-b border-[#2A2A32]">
                <th className="w-10 px-4 py-3">
                  <input
                    type="checkbox"
                    checked={selectedIds.size > 0 && selectedIds.size === filteredTransactions.filter((t) => !t.reconciled).length}
                    onChange={selectAll}
                    className="rounded border-[#3A3A45]"
                  />
                </th>
                <th className="text-left px-4 py-3 text-xs font-semibold text-[#5A5A6E] uppercase tracking-wider">Date</th>
                <th className="text-left px-4 py-3 text-xs font-semibold text-[#5A5A6E] uppercase tracking-wider">Description</th>
                <th className="text-left px-4 py-3 text-xs font-semibold text-[#5A5A6E] uppercase tracking-wider">Account</th>
                <th className="text-left px-4 py-3 text-xs font-semibold text-[#5A5A6E] uppercase tracking-wider">Reference</th>
                <th className="text-right px-4 py-3 text-xs font-semibold text-[#5A5A6E] uppercase tracking-wider">Amount</th>
                <th className="text-center px-4 py-3 text-xs font-semibold text-[#5A5A6E] uppercase tracking-wider">Status</th>
              </tr>
            </thead>
            <tbody className="divide-y divide-[#2A2A32]">
              {filteredTransactions.length === 0 ? (
                <tr>
                  <td colSpan={7} className="px-4 py-12 text-center">
                    <CheckCircle2 size={32} className="text-emerald-400 mx-auto mb-2" />
                    <p className="text-sm text-[#5A5A6E]">
                      {showReconciled ? 'No transactions found' : 'All transactions are reconciled!'}
                    </p>
                  </td>
                </tr>
              ) : (
                filteredTransactions.map((txn) => (
                  <tr
                    key={txn.id}
                    className={`hover:bg-[#222228] transition-colors ${
                      selectedIds.has(txn.id) ? 'bg-[#222228]' : ''
                    }`}
                  >
                    <td className="px-4 py-3">
                      {!txn.reconciled && (
                        <input
                          type="checkbox"
                          checked={selectedIds.has(txn.id)}
                          onChange={() => toggleSelect(txn.id)}
                          className="rounded border-[#3A3A45]"
                        />
                      )}
                    </td>
                    <td className="px-4 py-3 text-[#8B8B9E] whitespace-nowrap">
                      {new Date(txn.transactionDate).toLocaleDateString('en-US', {
                        month: 'short', day: 'numeric',
                      })}
                    </td>
                    <td className="px-4 py-3 text-[#F0F0F3] font-medium max-w-xs truncate">
                      {txn.description}
                    </td>
                    <td className="px-4 py-3 text-[#8B8B9E] text-xs whitespace-nowrap">
                      {txn.bankAccountName}
                    </td>
                    <td className="px-4 py-3 text-[#5A5A6E] text-xs font-mono">
                      {txn.referenceNumber || '—'}
                    </td>
                    <td className={`px-4 py-3 text-right font-semibold whitespace-nowrap ${
                      Number(txn.amount) >= 0 ? 'text-emerald-600' : 'text-red-600'
                    }`}>
                      {formatCurrency(Number(txn.amount))}
                    </td>
                    <td className="px-4 py-3 text-center">
                      {txn.reconciled ? (
                        <span className="inline-flex items-center gap-1 text-xs font-medium text-emerald-400 bg-emerald-900/25 px-2 py-0.5 rounded-full border border-emerald-700/50">
                          <CheckCircle2 size={12} /> Matched
                        </span>
                      ) : (
                        <span className="inline-flex items-center gap-1 text-xs font-medium text-amber-400 bg-amber-900/25 px-2 py-0.5 rounded-full border border-amber-700/50">
                          <AlertTriangle size={12} /> Unmatched
                        </span>
                      )}
                    </td>
                  </tr>
                ))
              )}
            </tbody>
          </table>
        </div>
      </div>
    </div>
  );
}
