import { useState } from 'react';
import {
  Title, Table, Badge, Group, Button, Stack, Text, Modal,
  TextInput, Textarea, Select, NumberInput, ActionIcon,
  Card, Loader, Center, Tooltip,
} from '@mantine/core';
import { DateInput } from '@mantine/dates';
import { useForm } from '@mantine/form';
import { useDisclosure } from '@mantine/hooks';
import { notifications } from '@mantine/notifications';
import { IconPlus, IconEye, IconCheck, IconX, IconTrash } from '@tabler/icons-react';
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
import api from '../../services/api';

interface JournalEntryLine {
  id?: string;
  account_id: string;
  account_name?: string;
  account_number?: number;
  debit: number;
  credit: number;
  memo: string;
}

interface JournalEntry {
  id: string;
  entry_date: string;
  description: string;
  reference_number: string;
  entry_type: string;
  is_posted: boolean;
  is_void: boolean;
  created_at: string;
  lines?: JournalEntryLine[];
  total_debit?: string;
  total_credit?: string;
}

interface Account {
  id: string;
  account_number: number;
  name: string;
}

export function TransactionsPage() {
  const [opened, { open, close }] = useDisclosure(false);
  const [viewId, setViewId] = useState<string | null>(null);
  const queryClient = useQueryClient();

  const { data: entries = [], isLoading } = useQuery<JournalEntry[]>({
    queryKey: ['journal-entries'],
    queryFn: async () => {
      const { data } = await api.get('/journal-entries');
      return data;
    },
  });

  const { data: accounts = [] } = useQuery<Account[]>({
    queryKey: ['accounts'],
    queryFn: async () => {
      const { data } = await api.get('/accounts');
      return data;
    },
  });

  const { data: viewEntry } = useQuery<JournalEntry>({
    queryKey: ['journal-entry', viewId],
    queryFn: async () => {
      const { data } = await api.get(`/journal-entries/${viewId}`);
      return data;
    },
    enabled: !!viewId,
  });

  const [lines, setLines] = useState<JournalEntryLine[]>([
    { account_id: '', debit: 0, credit: 0, memo: '' },
    { account_id: '', debit: 0, credit: 0, memo: '' },
  ]);

  const form = useForm({
    initialValues: {
      entry_date: new Date(),
      description: '',
      reference_number: '',
      entry_type: 'manual',
    },
    validate: {
      description: (v) => (v.length > 0 ? null : 'Required'),
    },
  });

  const createMutation = useMutation({
    mutationFn: async (values: any) => {
      const payload = {
        ...values,
        entry_date: values.entry_date.toISOString().split('T')[0],
        lines: lines.filter((l) => l.account_id && (l.debit > 0 || l.credit > 0)),
      };
      return api.post('/journal-entries', payload);
    },
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['journal-entries'] });
      notifications.show({ message: 'Journal entry created', color: 'green' });
      close();
      form.reset();
      setLines([
        { account_id: '', debit: 0, credit: 0, memo: '' },
        { account_id: '', debit: 0, credit: 0, memo: '' },
      ]);
    },
    onError: (err: any) => {
      notifications.show({ message: err.response?.data?.message || 'Error', color: 'red' });
    },
  });

  const postMutation = useMutation({
    mutationFn: (id: string) => api.post(`/journal-entries/${id}/post`),
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['journal-entries'] });
      queryClient.invalidateQueries({ queryKey: ['accounts'] });
      notifications.show({ message: 'Entry posted', color: 'green' });
    },
    onError: (err: any) => {
      notifications.show({ message: err.response?.data?.message || 'Post failed', color: 'red' });
    },
  });

  const voidMutation = useMutation({
    mutationFn: (id: string) => api.post(`/journal-entries/${id}/void`, { reason: 'Voided by user' }),
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['journal-entries'] });
      queryClient.invalidateQueries({ queryKey: ['accounts'] });
      notifications.show({ message: 'Entry voided', color: 'yellow' });
    },
  });

  const addLine = () => setLines([...lines, { account_id: '', debit: 0, credit: 0, memo: '' }]);
  const removeLine = (idx: number) => setLines(lines.filter((_, i) => i !== idx));
  const updateLine = (idx: number, field: string, value: any) => {
    const updated = [...lines];
    (updated[idx] as any)[field] = value;
    setLines(updated);
  };

  const totalDebit = lines.reduce((s, l) => s + (l.debit || 0), 0);
  const totalCredit = lines.reduce((s, l) => s + (l.credit || 0), 0);
  const isBalanced = Math.abs(totalDebit - totalCredit) < 0.01 && totalDebit > 0;

  const accountOptions = accounts.map((a) => ({
    value: a.id,
    label: `${a.account_number} - ${a.name}`,
  }));

  const fmt = (v: string | number) => {
    const n = typeof v === 'string' ? parseFloat(v) : v;
    return n.toLocaleString('en-US', { style: 'currency', currency: 'USD' });
  };

  if (isLoading) return <Center h={300}><Loader /></Center>;

  return (
    <Stack>
      <Group justify="space-between">
        <Title order={2}>Journal Entries</Title>
        <Button leftSection={<IconPlus size={16} />} onClick={open}>
          New Entry
        </Button>
      </Group>

      <Table striped highlightOnHover>
        <Table.Thead>
          <Table.Tr>
            <Table.Th>Date</Table.Th>
            <Table.Th>Description</Table.Th>
            <Table.Th>Type</Table.Th>
            <Table.Th>Ref #</Table.Th>
            <Table.Th ta="right">Debit</Table.Th>
            <Table.Th ta="right">Credit</Table.Th>
            <Table.Th>Status</Table.Th>
            <Table.Th>Actions</Table.Th>
          </Table.Tr>
        </Table.Thead>
        <Table.Tbody>
          {entries.map((e) => (
            <Table.Tr key={e.id} style={e.is_void ? { opacity: 0.5 } : undefined}>
              <Table.Td>{new Date(e.entry_date).toLocaleDateString()}</Table.Td>
              <Table.Td>{e.description}</Table.Td>
              <Table.Td><Badge size="sm" variant="light">{e.entry_type}</Badge></Table.Td>
              <Table.Td>{e.reference_number}</Table.Td>
              <Table.Td ta="right" ff="monospace">{fmt(e.total_debit || '0')}</Table.Td>
              <Table.Td ta="right" ff="monospace">{fmt(e.total_credit || '0')}</Table.Td>
              <Table.Td>
                {e.is_void ? (
                  <Badge color="red" variant="light" size="sm">Void</Badge>
                ) : e.is_posted ? (
                  <Badge color="green" variant="light" size="sm">Posted</Badge>
                ) : (
                  <Badge color="yellow" variant="light" size="sm">Draft</Badge>
                )}
              </Table.Td>
              <Table.Td>
                <Group gap="xs">
                  <Tooltip label="View">
                    <ActionIcon variant="subtle" onClick={() => setViewId(e.id)}>
                      <IconEye size={16} />
                    </ActionIcon>
                  </Tooltip>
                  {!e.is_posted && !e.is_void && (
                    <Tooltip label="Post">
                      <ActionIcon variant="subtle" color="green" onClick={() => postMutation.mutate(e.id)}>
                        <IconCheck size={16} />
                      </ActionIcon>
                    </Tooltip>
                  )}
                  {e.is_posted && !e.is_void && (
                    <Tooltip label="Void">
                      <ActionIcon variant="subtle" color="red" onClick={() => voidMutation.mutate(e.id)}>
                        <IconX size={16} />
                      </ActionIcon>
                    </Tooltip>
                  )}
                </Group>
              </Table.Td>
            </Table.Tr>
          ))}
          {entries.length === 0 && (
            <Table.Tr>
              <Table.Td colSpan={8}>
                <Text ta="center" c="dimmed" py="lg">No journal entries yet</Text>
              </Table.Td>
            </Table.Tr>
          )}
        </Table.Tbody>
      </Table>

      {/* New Entry Modal */}
      <Modal opened={opened} onClose={close} title="New Journal Entry" size="xl">
        <form onSubmit={form.onSubmit((values) => createMutation.mutate(values))}>
          <Stack>
            <Group grow>
              <DateInput label="Date" required {...form.getInputProps('entry_date')} />
              <TextInput label="Reference #" {...form.getInputProps('reference_number')} />
              <Select
                label="Type"
                data={[
                  { value: 'manual', label: 'Manual' },
                  { value: 'adjustment', label: 'Adjustment' },
                  { value: 'transfer', label: 'Transfer' },
                ]}
                {...form.getInputProps('entry_type')}
              />
            </Group>
            <Textarea label="Description" required {...form.getInputProps('description')} />

            <Text fw={500} size="sm">Line Items</Text>
            <Table>
              <Table.Thead>
                <Table.Tr>
                  <Table.Th>Account</Table.Th>
                  <Table.Th>Debit</Table.Th>
                  <Table.Th>Credit</Table.Th>
                  <Table.Th>Memo</Table.Th>
                  <Table.Th></Table.Th>
                </Table.Tr>
              </Table.Thead>
              <Table.Tbody>
                {lines.map((line, idx) => (
                  <Table.Tr key={idx}>
                    <Table.Td>
                      <Select
                        data={accountOptions}
                        searchable
                        value={line.account_id}
                        onChange={(v) => updateLine(idx, 'account_id', v || '')}
                        placeholder="Select account"
                      />
                    </Table.Td>
                    <Table.Td>
                      <NumberInput
                        value={line.debit}
                        onChange={(v) => updateLine(idx, 'debit', v || 0)}
                        min={0}
                        decimalScale={2}
                        prefix="$"
                      />
                    </Table.Td>
                    <Table.Td>
                      <NumberInput
                        value={line.credit}
                        onChange={(v) => updateLine(idx, 'credit', v || 0)}
                        min={0}
                        decimalScale={2}
                        prefix="$"
                      />
                    </Table.Td>
                    <Table.Td>
                      <TextInput
                        value={line.memo}
                        onChange={(e) => updateLine(idx, 'memo', e.currentTarget.value)}
                        placeholder="Memo"
                      />
                    </Table.Td>
                    <Table.Td>
                      {lines.length > 2 && (
                        <ActionIcon color="red" variant="subtle" onClick={() => removeLine(idx)}>
                          <IconTrash size={16} />
                        </ActionIcon>
                      )}
                    </Table.Td>
                  </Table.Tr>
                ))}
              </Table.Tbody>
              <Table.Tfoot>
                <Table.Tr>
                  <Table.Td><Button variant="subtle" size="xs" onClick={addLine}>+ Add Line</Button></Table.Td>
                  <Table.Td ta="right" fw={700}>{fmt(totalDebit)}</Table.Td>
                  <Table.Td ta="right" fw={700}>{fmt(totalCredit)}</Table.Td>
                  <Table.Td colSpan={2}>
                    {isBalanced ? (
                      <Badge color="green">Balanced</Badge>
                    ) : (
                      <Badge color="red">Out of balance: {fmt(Math.abs(totalDebit - totalCredit))}</Badge>
                    )}
                  </Table.Td>
                </Table.Tr>
              </Table.Tfoot>
            </Table>

            <Button type="submit" disabled={!isBalanced} loading={createMutation.isPending}>
              Create Journal Entry
            </Button>
          </Stack>
        </form>
      </Modal>

      {/* View Entry Modal */}
      <Modal opened={!!viewId} onClose={() => setViewId(null)} title="Journal Entry Detail" size="lg">
        {viewEntry && (
          <Stack>
            <Group>
              <Text fw={500}>Date:</Text>
              <Text>{new Date(viewEntry.entry_date).toLocaleDateString()}</Text>
              <Text fw={500}>Type:</Text>
              <Badge>{viewEntry.entry_type}</Badge>
              <Text fw={500}>Status:</Text>
              {viewEntry.is_void ? (
                <Badge color="red">Void</Badge>
              ) : viewEntry.is_posted ? (
                <Badge color="green">Posted</Badge>
              ) : (
                <Badge color="yellow">Draft</Badge>
              )}
            </Group>
            <Text><strong>Description:</strong> {viewEntry.description}</Text>
            {viewEntry.reference_number && <Text><strong>Ref #:</strong> {viewEntry.reference_number}</Text>}
            <Table>
              <Table.Thead>
                <Table.Tr>
                  <Table.Th>Account</Table.Th>
                  <Table.Th ta="right">Debit</Table.Th>
                  <Table.Th ta="right">Credit</Table.Th>
                  <Table.Th>Memo</Table.Th>
                </Table.Tr>
              </Table.Thead>
              <Table.Tbody>
                {viewEntry.lines?.map((l, i) => (
                  <Table.Tr key={i}>
                    <Table.Td>{l.account_number} - {l.account_name}</Table.Td>
                    <Table.Td ta="right" ff="monospace">{parseFloat(String(l.debit)) > 0 ? fmt(l.debit) : ''}</Table.Td>
                    <Table.Td ta="right" ff="monospace">{parseFloat(String(l.credit)) > 0 ? fmt(l.credit) : ''}</Table.Td>
                    <Table.Td>{l.memo}</Table.Td>
                  </Table.Tr>
                ))}
              </Table.Tbody>
            </Table>
          </Stack>
        )}
      </Modal>
    </Stack>
  );
}
