import { useState, useMemo, useEffect } from 'react';
import {
  Typography,
  Button,
  Space,
  DatePicker,
  Select,
  Modal,
  Form,
  Input,
  InputNumber,
  message,
  Tag,
  Tooltip,
  Dropdown,
  Skeleton,
  Empty,
  Descriptions,
  Table,
  Drawer,
} from 'antd';
import {
  PlusOutlined,
  FilterOutlined,
  EyeOutlined,
  EditOutlined,
  CopyOutlined,
  DeleteOutlined,
  MoreOutlined,
} from '@ant-design/icons';
import type { MenuProps } from 'antd';
import dayjs from 'dayjs';
import DataTable, { DataTableColumn } from '@/components/tables/DataTable';
import { useCompanyStore } from '@/stores/companyStore';
import { useActiveAccounts } from '@/api/queries/accountQueries';
import { useJournalEntryDrafts } from '@/api/queries/draftQueries';
import { formatCurrency } from '@/lib/formatters';
import { PageHeader } from '@/components/shared/PageHeader';
import { validateDoubleEntry } from '@/lib/accounting';
import type { TransactionLine, JournalEntryDraft, JournalEntryDraftStatus } from '@/types/accounting';
import { useCreateJournalEntryDraft, useUpdateJournalEntryDraft, useDiscardJournalEntryDraft } from '@/api/mutations/draftMutations';
import { usePeriodStore } from '@/stores/periodStore';

const { Text } = Typography;
const { RangePicker } = DatePicker;

// Display type for journal entry drafts
interface DraftDisplay {
  id: string;
  transactionNumber: string;
  date: string;
  description: string;
  totalDebit: number;
  totalCredit: number;
  isReconciled: boolean;
  isVoided: boolean;
  status: JournalEntryDraftStatus;
  lines: JournalEntryDraft['lines'];
  postedAt?: string;
  postedBy?: string;
}

export default function Kassekladde() {
  const { activeCompany } = useCompanyStore();
  const [isModalOpen, setIsModalOpen] = useState(false);
  const [editingDraft, setEditingDraft] = useState<DraftDisplay | null>(null);
  const [dateFilter, setDateFilter] = useState<[dayjs.Dayjs, dayjs.Dayjs] | null>(null);
  const [accountFilter, setAccountFilter] = useState<string | null>(null);
  const [statusFilter, setStatusFilter] = useState<string | null>(null);
  const [showAdvancedFilters, setShowAdvancedFilters] = useState(false);
  const [detailDraft, setDetailDraft] = useState<DraftDisplay | null>(null);
  const [form] = Form.useForm();
  const [lines, setLines] = useState<Partial<TransactionLine>[]>([
    { debit: 0, credit: 0 },
    { debit: 0, credit: 0 },
  ]);

  const { currentFiscalYear } = usePeriodStore();

  // Mutation hooks
  const createDraftMutation = useCreateJournalEntryDraft();
  const updateDraftMutation = useUpdateJournalEntryDraft();
  const discardDraftMutation = useDiscardJournalEntryDraft();

  // Fetch accounts and drafts from API
  const { data: accounts = [], isLoading: accountsLoading } = useActiveAccounts(activeCompany?.id);
  const { data: drafts = [], isLoading: draftsLoading } = useJournalEntryDrafts(activeCompany?.id);

  const isLoading = accountsLoading || draftsLoading;

  // Convert drafts to display format
  const displayData: DraftDisplay[] = useMemo(() => drafts.map(draft => ({
    id: draft.id,
    transactionNumber: draft.voucherNumber || draft.name,
    date: draft.documentDate || draft.createdAt,
    description: draft.description || draft.name,
    lines: draft.lines || [],
    totalDebit: draft.lines?.reduce((sum, l) => sum + (l.debitAmount || 0), 0) ?? 0,
    totalCredit: draft.lines?.reduce((sum, l) => sum + (l.creditAmount || 0), 0) ?? 0,
    isReconciled: draft.status === 'posted',
    isVoided: draft.status === 'discarded',
    status: draft.status,
    postedAt: draft.status === 'posted' ? draft.updatedAt : undefined,
    postedBy: draft.createdBy,
  })), [drafts]);

  // Apply filters to display data
  const filteredData: DraftDisplay[] = useMemo(() => {
    let data = displayData;

    // Date filter
    if (dateFilter && dateFilter[0] && dateFilter[1]) {
      const startDate = dateFilter[0].startOf('day');
      const endDate = dateFilter[1].endOf('day');
      data = data.filter(d => {
        const dDate = dayjs(d.date);
        return (dDate.isAfter(startDate) || dDate.isSame(startDate, 'day')) &&
               (dDate.isBefore(endDate) || dDate.isSame(endDate, 'day'));
      });
    }

    // Account filter - filter drafts where any line references the selected account
    if (accountFilter) {
      data = data.filter(d =>
        d.lines.some(l => l.accountId === accountFilter)
      );
    }

    // Status filter
    if (statusFilter) {
      data = data.filter(d => d.status === statusFilter);
    }

    return data;
  }, [displayData, dateFilter, accountFilter, statusFilter]);

  // Pre-populate form when editing a draft
  useEffect(() => {
    if (editingDraft && isModalOpen) {
      form.setFieldsValue({
        date: editingDraft.date ? dayjs(editingDraft.date) : dayjs(),
        description: editingDraft.description,
      });
      // Populate lines from the draft
      if (editingDraft.lines && editingDraft.lines.length > 0) {
        setLines(editingDraft.lines.map(l => ({
          accountId: l.accountId,
          debit: l.debitAmount || 0,
          credit: l.creditAmount || 0,
          description: l.description,
          vatCode: l.vatCode,
        })));
      } else {
        setLines([{ debit: 0, credit: 0 }, { debit: 0, credit: 0 }]);
      }
    }
  }, [editingDraft, isModalOpen, form]);

  const columns: DataTableColumn<DraftDisplay>[] = [
    {
      dataIndex: 'transactionNumber',
      title: 'Bilagsnr.',
      width: 120,
      sortable: true,
      render: (value) => <Text strong>#{value as string}</Text>,
    },
    {
      dataIndex: 'date',
      title: 'Dato',
      width: 100,
      sortable: true,
      columnType: 'date',
    },
    {
      dataIndex: 'description',
      title: 'Beskrivelse',
      ellipsis: true,
    },
    {
      dataIndex: 'totalDebit',
      title: 'Debet',
      width: 120,
      sortable: true,
      columnType: 'currency',
    },
    {
      dataIndex: 'totalCredit',
      title: 'Kredit',
      width: 120,
      sortable: true,
      columnType: 'currency',
    },
    {
      dataIndex: 'isReconciled',
      title: 'Status',
      width: 100,
      render: (value, record) => {
        if (record.isVoided) {
          return <Tag color="red">Annulleret</Tag>;
        }
        return value ? (
          <Tag color="green">Bogført</Tag>
        ) : (
          <Tag color="orange">Kladde</Tag>
        );
      },
    },
    {
      dataIndex: 'id',
      title: '',
      width: 50,
      render: (_, record) => {
        const menuItems: MenuProps['items'] = [
          {
            key: 'view',
            icon: <EyeOutlined />,
            label: 'Vis detaljer',
          },
          {
            key: 'edit',
            icon: <EditOutlined />,
            label: 'Rediger',
            disabled: record.isReconciled || record.isVoided,
          },
          {
            key: 'copy',
            icon: <CopyOutlined />,
            label: 'Kopier',
          },
          {
            type: 'divider',
          },
          {
            key: 'void',
            icon: <DeleteOutlined />,
            label: 'Annuller',
            danger: true,
            disabled: record.isVoided,
          },
        ];

        return (
          <Dropdown
            menu={{
              items: menuItems,
              onClick: ({ key }) => handleAction(key, record),
            }}
            trigger={['click']}
          >
            <Button type="text" icon={<MoreOutlined />} size="small" />
          </Dropdown>
        );
      },
    },
  ];

  const handleAction = (action: string, record: DraftDisplay) => {
    switch (action) {
      case 'view':
        setDetailDraft(record);
        break;
      case 'edit':
        setEditingDraft(record);
        setIsModalOpen(true);
        break;
      case 'copy':
        if (!activeCompany) {
          message.error('Ingen virksomhed valgt');
          break;
        }
        (async () => {
          try {
            const draft = await createDraftMutation.mutateAsync({
              companyId: activeCompany.id,
              name: `Kopi af ${record.description}`,
              description: record.description,
              fiscalYearId: currentFiscalYear?.id,
            });
            // Copy lines to the new draft
            if (record.lines && record.lines.length > 0) {
              await updateDraftMutation.mutateAsync({
                id: draft.id,
                lines: record.lines.map((l, idx) => ({
                  lineNumber: idx + 1,
                  accountId: l.accountId,
                  debitAmount: l.debitAmount || 0,
                  creditAmount: l.creditAmount || 0,
                  description: l.description,
                  vatCode: l.vatCode,
                })),
              });
            }
            message.success(`Bilag ${record.transactionNumber} kopieret`);
          } catch (error) {
            if (error instanceof Error) {
              message.error(`Fejl ved kopiering: ${error.message}`);
            }
          }
        })();
        break;
      case 'void':
        Modal.confirm({
          title: 'Annuller bilag',
          content: `Er du sikker på at du vil annullere bilag ${record.transactionNumber}?`,
          okText: 'Annuller bilag',
          okType: 'danger',
          cancelText: 'Fortryd',
          onOk: async () => {
            try {
              await discardDraftMutation.mutateAsync(record.id);
              message.success(`Bilag ${record.transactionNumber} annulleret`);
            } catch (error) {
              if (error instanceof Error) {
                message.error(`Fejl ved annullering: ${error.message}`);
              }
            }
          },
        });
        break;
    }
  };

  const handleAddLine = () => {
    setLines([...lines, { debit: 0, credit: 0 }]);
  };

  const handleRemoveLine = (index: number) => {
    if (lines.length > 2) {
      setLines(lines.filter((_, i) => i !== index));
    }
  };

  const handleLineChange = (index: number, field: string, value: unknown) => {
    const newLines = [...lines];
    newLines[index] = { ...newLines[index], [field]: value };

    // Auto-balance: if debit is entered, clear credit and vice versa
    if (field === 'debit' && value) {
      newLines[index].credit = 0;
    } else if (field === 'credit' && value) {
      newLines[index].debit = 0;
    }

    setLines(newLines);
  };

  const handleSubmit = async () => {
    try {
      const values = await form.validateFields();

      // Validate double-entry
      const validation = validateDoubleEntry(lines as TransactionLine[]);
      if (!validation.valid) {
        message.error(
          `Debet (${formatCurrency(validation.totalDebit)}) skal være lig kredit (${formatCurrency(validation.totalCredit)})`
        );
        return;
      }

      if (!activeCompany) {
        message.error('Ingen virksomhed valgt');
        return;
      }

      if (editingDraft) {
        // Update existing draft
        await updateDraftMutation.mutateAsync({
          id: editingDraft.id,
          name: values.description,
          documentDate: values.date?.format('YYYY-MM-DD'),
          description: values.description,
          fiscalYearId: currentFiscalYear?.id,
          lines: lines
            .filter(l => l.accountId)
            .map((l, idx) => ({
              lineNumber: idx + 1,
              accountId: l.accountId!,
              debitAmount: l.debit || 0,
              creditAmount: l.credit || 0,
              description: l.description,
              vatCode: l.vatCode,
            })),
        });
        message.success('Bilag opdateret');
      } else {
        // Create new draft
        const draft = await createDraftMutation.mutateAsync({
          companyId: activeCompany.id,
          name: values.description,
          documentDate: values.date?.format('YYYY-MM-DD'),
          description: values.description,
          fiscalYearId: currentFiscalYear?.id,
        });

        // Update the draft with lines
        if (lines.some(l => l.accountId)) {
          await updateDraftMutation.mutateAsync({
            id: draft.id,
            lines: lines
              .filter(l => l.accountId)
              .map((l, idx) => ({
                lineNumber: idx + 1,
                accountId: l.accountId!,
                debitAmount: l.debit || 0,
                creditAmount: l.credit || 0,
                description: l.description,
                vatCode: l.vatCode,
              })),
          });
        }
        message.success('Bilag oprettet');
      }

      setIsModalOpen(false);
      setEditingDraft(null);
      form.resetFields();
      setLines([{ debit: 0, credit: 0 }, { debit: 0, credit: 0 }]);
    } catch (error) {
      if (error instanceof Error) {
        message.error(`Fejl: ${error.message}`);
      }
    }
  };

  // Helper to look up account name by ID
  const getAccountName = (accountId: string): string => {
    const acc = accounts.find(a => a.id === accountId);
    return acc ? `${acc.accountNumber} - ${acc.name}` : accountId;
  };

  const getStatusLabel = (status: JournalEntryDraftStatus): { label: string; color: string } => {
    switch (status) {
      case 'posted': return { label: 'Bogført', color: 'green' };
      case 'discarded': return { label: 'Annulleret', color: 'red' };
      case 'draft': return { label: 'Kladde', color: 'orange' };
      case 'pending_review': return { label: 'Afventer gennemgang', color: 'blue' };
      case 'approved': return { label: 'Godkendt', color: 'cyan' };
      default: return { label: status, color: 'default' };
    }
  };

  const balance = validateDoubleEntry(lines as TransactionLine[]);

  if (isLoading) {
    return (
      <div>
        <PageHeader
          title="Kassekladde"
          subtitle={activeCompany?.name}
          breadcrumbs={[{ title: 'Bogføring', path: '/kontooversigt' }, { title: 'Kassekladde' }]}
        />
        <Skeleton active paragraph={{ rows: 10 }} />
      </div>
    );
  }

  return (
    <div>
      <PageHeader
        title="Kassekladde"
        subtitle={activeCompany?.name}
        breadcrumbs={[{ title: 'Bogføring', path: '/kontooversigt' }, { title: 'Kassekladde' }]}
        extra={
          <Button
            type="primary"
            icon={<PlusOutlined />}
            onClick={() => {
              setEditingDraft(null);
              form.resetFields();
              setLines([{ debit: 0, credit: 0 }, { debit: 0, credit: 0 }]);
              setIsModalOpen(true);
            }}
          >
            Nyt bilag
          </Button>
        }
      />

      {/* Filters */}
      <Space style={{ marginBottom: 16 }} wrap>
        <RangePicker
          placeholder={['Fra dato', 'Til dato']}
          value={dateFilter}
          onChange={(dates) => setDateFilter(dates as [dayjs.Dayjs, dayjs.Dayjs] | null)}
          format="DD-MM-YYYY"
        />
        {showAdvancedFilters && (
          <>
            <Select
              placeholder="Konto"
              style={{ width: 200 }}
              allowClear
              value={accountFilter}
              onChange={(value) => setAccountFilter(value ?? null)}
              options={accounts.map((acc) => ({
                value: acc.id,
                label: `${acc.accountNumber} - ${acc.name}`,
              }))}
            />
            <Select
              placeholder="Status"
              style={{ width: 120 }}
              allowClear
              value={statusFilter}
              onChange={(value) => setStatusFilter(value ?? null)}
              options={[
                { value: 'posted', label: 'Bogført' },
                { value: 'draft', label: 'Kladde' },
                { value: 'discarded', label: 'Annulleret' },
              ]}
            />
          </>
        )}
        <Button
          icon={<FilterOutlined />}
          type={showAdvancedFilters ? 'primary' : 'default'}
          ghost={showAdvancedFilters}
          onClick={() => {
            setShowAdvancedFilters(!showAdvancedFilters);
            if (showAdvancedFilters) {
              // Clear advanced filters when hiding
              setAccountFilter(null);
              setStatusFilter(null);
            }
          }}
        >
          {showAdvancedFilters ? 'Skjul filtre' : 'Flere filtre'}
        </Button>
      </Space>

      {/* Data Table */}
      {filteredData.length === 0 ? (
        <Empty description="Ingen bilag fundet. Opret et nyt bilag for at komme i gang." />
      ) : (
        <DataTable<DraftDisplay>
          data={filteredData}
          columns={columns}
          exportFilename="kassekladde"
          rowSelection="multiple"
          onRowClick={(record) => handleAction('view', record)}
          rowClassName={(record) =>
            record.isVoided ? 'voided-row' : ''
          }
        />
      )}

      {/* Detail Drawer */}
      <Drawer
        title={`Bilag #${detailDraft?.transactionNumber ?? ''}`}
        open={!!detailDraft}
        onClose={() => setDetailDraft(null)}
        width={600}
      >
        {detailDraft && (
          <>
            <Descriptions bordered column={1} size="small">
              <Descriptions.Item label="Bilagsnr.">
                #{detailDraft.transactionNumber}
              </Descriptions.Item>
              <Descriptions.Item label="Dato">
                {detailDraft.date ? dayjs(detailDraft.date).format('DD-MM-YYYY') : '-'}
              </Descriptions.Item>
              <Descriptions.Item label="Beskrivelse">
                {detailDraft.description}
              </Descriptions.Item>
              <Descriptions.Item label="Status">
                <Tag color={getStatusLabel(detailDraft.status).color}>
                  {getStatusLabel(detailDraft.status).label}
                </Tag>
              </Descriptions.Item>
              {detailDraft.isReconciled && detailDraft.postedAt && (
                <Descriptions.Item label="Bogført">
                  {dayjs(detailDraft.postedAt).format('DD-MM-YYYY HH:mm')}
                </Descriptions.Item>
              )}
              {detailDraft.postedBy && (
                <Descriptions.Item label="Bogført af">
                  {detailDraft.postedBy}
                </Descriptions.Item>
              )}
              <Descriptions.Item label="Total debet">
                {formatCurrency(detailDraft.totalDebit)}
              </Descriptions.Item>
              <Descriptions.Item label="Total kredit">
                {formatCurrency(detailDraft.totalCredit)}
              </Descriptions.Item>
            </Descriptions>

            <Typography.Title level={5} style={{ marginTop: 24, marginBottom: 12 }}>
              Posteringslinjer
            </Typography.Title>
            <Table
              dataSource={detailDraft.lines.map((l, idx) => ({ ...l, key: idx }))}
              columns={[
                {
                  title: 'Konto',
                  dataIndex: 'accountId',
                  key: 'account',
                  render: (accountId: string) => getAccountName(accountId),
                },
                {
                  title: 'Debet',
                  dataIndex: 'debitAmount',
                  key: 'debit',
                  align: 'right' as const,
                  render: (v: number) => v ? formatCurrency(v) : '-',
                },
                {
                  title: 'Kredit',
                  dataIndex: 'creditAmount',
                  key: 'credit',
                  align: 'right' as const,
                  render: (v: number) => v ? formatCurrency(v) : '-',
                },
                {
                  title: 'Tekst',
                  dataIndex: 'description',
                  key: 'description',
                  render: (v: string) => v || '-',
                },
              ]}
              pagination={false}
              size="small"
            />
          </>
        )}
      </Drawer>

      {/* Create/Edit Modal */}
      <Modal
        title={editingDraft ? 'Rediger bilag' : 'Nyt bilag'}
        open={isModalOpen}
        onCancel={() => {
          setIsModalOpen(false);
          setEditingDraft(null);
          form.resetFields();
          setLines([{ debit: 0, credit: 0 }, { debit: 0, credit: 0 }]);
        }}
        onOk={handleSubmit}
        okText="Gem"
        cancelText="Annuller"
        width={800}
      >
        <Form form={form} layout="vertical">
          <Space style={{ width: '100%' }} direction="vertical" size="middle">
            <Space style={{ width: '100%' }}>
              <Form.Item
                name="date"
                label="Dato"
                rules={[{ required: true, message: 'Vælg dato' }]}
                initialValue={dayjs()}
              >
                <DatePicker format="DD-MM-YYYY" style={{ width: 150 }} />
              </Form.Item>
              <Form.Item
                name="description"
                label="Beskrivelse"
                rules={[{ required: true, message: 'Indtast beskrivelse' }]}
                style={{ flex: 1 }}
              >
                <Input placeholder="F.eks. Faktura #1234 til kunde" />
              </Form.Item>
            </Space>

            {/* Transaction Lines */}
            <div>
              <Text strong style={{ display: 'block', marginBottom: 8 }}>
                Posteringslinjer
              </Text>
              <table style={{ width: '100%', borderCollapse: 'collapse' }}>
                <thead>
                  <tr style={{ borderBottom: '1px solid #f0f0f0' }}>
                    <th style={{ textAlign: 'left', padding: 8, width: '40%' }}>Konto</th>
                    <th style={{ textAlign: 'right', padding: 8, width: '20%' }}>Debet</th>
                    <th style={{ textAlign: 'right', padding: 8, width: '20%' }}>Kredit</th>
                    <th style={{ textAlign: 'left', padding: 8, width: '15%' }}>Tekst</th>
                    <th style={{ width: '5%' }}></th>
                  </tr>
                </thead>
                <tbody>
                  {lines.map((line, index) => (
                    <tr key={index}>
                      <td style={{ padding: 4 }}>
                        <Select
                          style={{ width: '100%' }}
                          placeholder="Vælg konto"
                          showSearch
                          optionFilterProp="label"
                          value={line.accountId}
                          onChange={(value) => handleLineChange(index, 'accountId', value)}
                          options={accounts.map((acc) => ({
                            value: acc.id,
                            label: `${acc.accountNumber} - ${acc.name}`,
                          }))}
                        />
                      </td>
                      <td style={{ padding: 4 }}>
                        <InputNumber
                          style={{ width: '100%' }}
                          min={0}
                          precision={2}
                          value={line.debit}
                          onChange={(value) => handleLineChange(index, 'debit', value || 0)}
                          formatter={(value) =>
                            `${value}`.replace(/\B(?=(\d{3})+(?!\d))/g, '.')
                          }
                          parser={(value) =>
                            value?.replace(/\./g, '').replace(',', '.') as unknown as number
                          }
                        />
                      </td>
                      <td style={{ padding: 4 }}>
                        <InputNumber
                          style={{ width: '100%' }}
                          min={0}
                          precision={2}
                          value={line.credit}
                          onChange={(value) => handleLineChange(index, 'credit', value || 0)}
                          formatter={(value) =>
                            `${value}`.replace(/\B(?=(\d{3})+(?!\d))/g, '.')
                          }
                          parser={(value) =>
                            value?.replace(/\./g, '').replace(',', '.') as unknown as number
                          }
                        />
                      </td>
                      <td style={{ padding: 4 }}>
                        <Input
                          placeholder="Valgfri"
                          value={line.description}
                          onChange={(e) =>
                            handleLineChange(index, 'description', e.target.value)
                          }
                        />
                      </td>
                      <td style={{ padding: 4 }}>
                        {lines.length > 2 && (
                          <Button
                            type="text"
                            danger
                            size="small"
                            onClick={() => handleRemoveLine(index)}
                          >
                            x
                          </Button>
                        )}
                      </td>
                    </tr>
                  ))}
                </tbody>
                <tfoot>
                  <tr style={{ borderTop: '2px solid #f0f0f0' }}>
                    <td style={{ padding: 8 }}>
                      <Button type="dashed" size="small" onClick={handleAddLine}>
                        + Tilføj linje
                      </Button>
                    </td>
                    <td
                      style={{
                        padding: 8,
                        textAlign: 'right',
                        fontWeight: 'bold',
                      }}
                    >
                      {formatCurrency(balance.totalDebit)}
                    </td>
                    <td
                      style={{
                        padding: 8,
                        textAlign: 'right',
                        fontWeight: 'bold',
                      }}
                    >
                      {formatCurrency(balance.totalCredit)}
                    </td>
                    <td colSpan={2} style={{ padding: 8 }}>
                      {!balance.valid && (
                        <Tooltip title={`Differens: ${formatCurrency(balance.difference)}`}>
                          <Tag color="red">Ubalance!</Tag>
                        </Tooltip>
                      )}
                      {balance.valid && balance.totalDebit > 0 && (
                        <Tag color="green">Balancerer</Tag>
                      )}
                    </td>
                  </tr>
                </tfoot>
              </table>
            </div>
          </Space>
        </Form>
      </Modal>
    </div>
  );
}
