import { useState, useMemo, useEffect, CSSProperties } from 'react';
import {
  Card,
  Form,
  Input,
  InputNumber,
  Button,
  Row,
  Col,
  Statistic,
  Table,
  Alert,
  Typography,
  Collapse,
  Radio,
  Tooltip,
  message,
  Grid,
  Space
} from 'antd';
import {
  CalculatorOutlined,
  ReloadOutlined,
  DownloadOutlined,
  InfoCircleOutlined,
  DollarOutlined,
  PercentageOutlined,
  CalendarOutlined
} from '@ant-design/icons';
import { useApi } from '@/hooks/useApi';
import { LoanCalculationsService } from '@/services/loanCalculations';
import { CalculatorConfigurationService } from '@/services/calculatorConfiguration';
import { parseError } from '@/utils/errorHandler';
import type { ColumnsType } from 'antd/es/table';

const { Title, Text } = Typography;
const { Panel } = Collapse;
const { useBreakpoint } = Grid;

interface CalculatorDefaults {
  id: string;
  default_principal?: number;
  default_interest_rate?: number;
  default_term_months?: number;
  min_principal?: number;
  max_principal?: number;
  min_interest_rate?: number;
  max_interest_rate?: number;
  min_term_months?: number;
  max_term_months?: number;
  created_at: string;
  updated_at: string;
}

interface LoanCalculation {
  id: string;
  principal?: number;
  annual_interest_rate?: number;
  loan_term_months?: number;
  monthly_payment?: number;
  total_payment?: number;
  total_interest?: number;
  session_id?: string;
  created_at: string;
  updated_at: string;
}

interface AmortizationEntry {
  payment_number: number;
  payment_date: string;
  payment_amount: number;
  principal_portion: number;
  interest_portion: number;
  remaining_balance: number;
}

interface LoanCalculationDetail extends LoanCalculation {
  amortization_schedule_entries?: AmortizationEntry[];
}

interface PaginatedScheduleResponse {
  items: AmortizationEntry[];
  total: number;
  limit: number;
  offset: number;
}

interface StatCardProps {
  title: string;
  value: number;
  prefix?: string;
  precision?: number;
  loading?: boolean;
}

const StatCard = ({ title, value, prefix = '$', precision = 2, loading = false }: StatCardProps) => {
  const screens = useBreakpoint();
  return (
    <Card bordered={false} loading={loading} style={{ height: '100%' }}>
      <Statistic
        title={title}
        value={value}
        prefix={prefix}
        precision={precision}
        valueStyle={{
          fontSize: screens.xs ? '20px' : '28px',
          fontWeight: 600,
          color: '#1890ff'
        }}
      />
    </Card>
  );
};

const LoanCalculatorPage = () => {
  const [messageApi, contextHolder] = message.useMessage();
  const [form] = Form.useForm();
  const screens = useBreakpoint();

  const [termUnit, setTermUnit] = useState<'months' | 'years'>('months');
  const [calculationResult, setCalculationResult] = useState<LoanCalculation | null>(null);
  const [scheduleVisible, setScheduleVisible] = useState(false);
  const [scheduleData, setScheduleData] = useState<AmortizationEntry[]>([]);
  const [scheduleTotal, setScheduleTotal] = useState(0);
  const [schedulePage, setSchedulePage] = useState(1);
  const [schedulePageSize, setSchedulePageSize] = useState(20);
  const [loadingSchedule, setLoadingSchedule] = useState(false);
  const [calculating, setCalculating] = useState(false);

  const { data: defaults, loading: loadingDefaults, error: defaultsError, execute: fetchDefaults } = useApi<CalculatorDefaults>(
    CalculatorConfigurationService.list
  );

  useEffect(() => {
    void fetchDefaults();
  }, [fetchDefaults]);

  useEffect(() => {
    if (defaults) {
      form.setFieldsValue({
        principal: defaults.default_principal ?? 250000,
        annual_interest_rate: defaults.default_interest_rate ?? 6.5,
        loan_term: defaults.default_term_months ?? 360
      });
    }
  }, [defaults, form]);

  useEffect(() => {
    if (defaultsError) {
      const { message: errorMsg } = parseError(defaultsError);
      messageApi.error(errorMsg);
    }
  }, [defaultsError, messageApi]);

  const minPrincipal = defaults?.min_principal ?? 1000;
  const maxPrincipal = defaults?.max_principal ?? 10000000;
  const minRate = defaults?.min_interest_rate ?? 0;
  const maxRate = defaults?.max_interest_rate ?? 50;
  const minTermMonths = defaults?.min_term_months ?? 1;
  const maxTermMonths = defaults?.max_term_months ?? 600;

  const handleCalculate = async () => {
    try {
      const values = await form.validateFields();
      setCalculating(true);

      const termInMonths = termUnit === 'years' ? values.loan_term * 12 : values.loan_term;
      const principal = values.principal;
      const annualRate = values.annual_interest_rate;

      const monthlyRate = annualRate / 100 / 12;
      const monthlyPayment =
        monthlyRate === 0
          ? principal / termInMonths
          : (principal * monthlyRate * Math.pow(1 + monthlyRate, termInMonths)) /
            (Math.pow(1 + monthlyRate, termInMonths) - 1);

      const totalPayment = monthlyPayment * termInMonths;
      const totalInterest = totalPayment - principal;

      const response = await LoanCalculationsService.create({
        principal,
        annual_interest_rate: annualRate,
        loan_term_months: termInMonths,
        monthly_payment: monthlyPayment,
        total_payment: totalPayment,
        total_interest: totalInterest
      });

      setCalculationResult(response.data);
      messageApi.success('Calculation completed successfully');
      setScheduleVisible(false);
      setScheduleData([]);
    } catch (e) {
      const { message: errorMsg } = parseError(e);
      messageApi.error(errorMsg);
    } finally {
      setCalculating(false);
    }
  };

  const handleReset = () => {
    form.setFieldsValue({
      principal: defaults?.default_principal ?? 250000,
      annual_interest_rate: defaults?.default_interest_rate ?? 6.5,
      loan_term: defaults?.default_term_months ?? 360
    });
    setTermUnit('months');
    setCalculationResult(null);
    setScheduleVisible(false);
    setScheduleData([]);
    messageApi.info('Form reset to default values');
  };

  const handleGenerateSchedule = async () => {
    if (!calculationResult?.id) {
      messageApi.warning('Please calculate a loan first');
      return;
    }

    try {
      setLoadingSchedule(true);
      const startDate = new Date().toISOString().split('T')[0];
      const response = await LoanCalculationsService.createGenerateSchedule(calculationResult.id);

      if (response.data.amortization_schedule_entries) {
        setScheduleData(response.data.amortization_schedule_entries);
        setScheduleTotal(response.data.amortization_schedule_entries.length);
        setScheduleVisible(true);
        messageApi.success('Amortization schedule generated');
      }
    } catch (e) {
      const { message: errorMsg } = parseError(e);
      messageApi.error(errorMsg);
    } finally {
      setLoadingSchedule(false);
    }
  };

  const handleExportCSV = () => {
    if (scheduleData.length === 0) {
      messageApi.warning('No schedule data to export');
      return;
    }

    const headers = [
      'Payment #',
      'Payment Date',
      'Payment Amount',
      'Principal Portion',
      'Interest Portion',
      'Remaining Balance'
    ];

    const csvContent = [
      headers.join(','),
      ...scheduleData.map(entry =>
        [
          entry.payment_number,
          entry.payment_date,
          entry.payment_amount.toFixed(2),
          entry.principal_portion.toFixed(2),
          entry.interest_portion.toFixed(2),
          entry.remaining_balance.toFixed(2)
        ].join(',')
      )
    ].join('\n');

    const blob = new Blob([csvContent], { type: 'text/csv;charset=utf-8;' });
    const link = document.createElement('a');
    const url = URL.createObjectURL(blob);
    link.setAttribute('href', url);
    link.setAttribute('download', `amortization_schedule_${new Date().getTime()}.csv`);
    link.style.visibility = 'hidden';
    document.body.appendChild(link);
    link.click();
    document.body.removeChild(link);

    messageApi.success('Schedule exported successfully');
  };

  const milestoneRowIndex = useMemo(() => {
    return scheduleData.findIndex(entry => entry.principal_portion > entry.interest_portion);
  }, [scheduleData]);

  const scheduleColumns: ColumnsType<AmortizationEntry> = useMemo(
    () => [
      {
        title: 'Payment #',
        dataIndex: 'payment_number',
        key: 'payment_number',
        width: 100,
        fixed: screens.lg ? undefined : 'left'
      },
      {
        title: 'Payment Date',
        dataIndex: 'payment_date',
        key: 'payment_date',
        width: 130,
        responsive: ['md']
      },
      {
        title: 'Payment Amount',
        dataIndex: 'payment_amount',
        key: 'payment_amount',
        width: 150,
        render: (val: number) => `$${val?.toFixed(2) ?? '0.00'}`
      },
      {
        title: 'Principal',
        dataIndex: 'principal_portion',
        key: 'principal_portion',
        width: 130,
        render: (val: number) => `$${val?.toFixed(2) ?? '0.00'}`
      },
      {
        title: 'Interest',
        dataIndex: 'interest_portion',
        key: 'interest_portion',
        width: 130,
        render: (val: number) => `$${val?.toFixed(2) ?? '0.00'}`
      },
      {
        title: 'Remaining Balance',
        dataIndex: 'remaining_balance',
        key: 'remaining_balance',
        width: 160,
        render: (val: number) => `$${val?.toFixed(2) ?? '0.00'}`
      }
    ],
    [screens.lg]
  );

  const paginatedSchedule = useMemo(() => {
    const start = (schedulePage - 1) * schedulePageSize;
    const end = start + schedulePageSize;
    return scheduleData.slice(start, end);
  }, [scheduleData, schedulePage, schedulePageSize]);

  const principalPercentage = useMemo(() => {
    if (!calculationResult?.total_payment || !calculationResult?.principal) return 0;
    return ((calculationResult.principal / calculationResult.total_payment) * 100).toFixed(1);
  }, [calculationResult]);

  const interestPercentage = useMemo(() => {
    if (!calculationResult?.total_payment || !calculationResult?.total_interest) return 0;
    return ((calculationResult.total_interest / calculationResult.total_payment) * 100).toFixed(1);
  }, [calculationResult]);

  const padding = screens.xs ? 12 : 24;

  return (
    <div style={{ padding, minHeight: '100%' }}>
      {contextHolder}
      <Title level={screens.xs ? 3 : 2} style={{ marginBottom: 24 }}>
        Loan Calculator
      </Title>

      <Row gutter={[16, 16]}>
        <Col xs={24} lg={12}>
          <Card
            title="Loan Parameters"
            bordered={false}
            style={{ height: '100%' }}
            loading={loadingDefaults}
          >
            <Form form={form} layout="vertical">
              <Row gutter={[16, 16]}>
                <Col xs={24}>
                  <Form.Item
                    label={
                      <span>
                        Principal Amount{' '}
                        <Tooltip title="The total amount of money you are borrowing">
                          <InfoCircleOutlined />
                        </Tooltip>
                      </span>
                    }
                    name="principal"
                    rules={[
                      { required: true, message: 'Principal is required' },
                      {
                        type: 'number',
                        min: minPrincipal,
                        max: maxPrincipal,
                        message: `Principal must be between $${minPrincipal.toLocaleString()} and $${maxPrincipal.toLocaleString()}`
                      }
                    ]}
                  >
                    <InputNumber
                      prefix={<DollarOutlined />}
                      formatter={value => `${value}`.replace(/\B(?=(\d{3})+(?!\d))/g, ',')}
                      parser={value => (value ? value.replace(/\$\s?|(,*)/g, '') : '')}
                      style={{ width: '100%' }}
                      placeholder="Enter principal amount"
                    />
                  </Form.Item>
                </Col>

                <Col xs={24}>
                  <Form.Item
                    label={
                      <span>
                        Annual Interest Rate{' '}
                        <Tooltip title="The yearly interest rate on your loan">
                          <InfoCircleOutlined />
                        </Tooltip>
                      </span>
                    }
                    name="annual_interest_rate"
                    rules={[
                      { required: true, message: 'Interest rate is required' },
                      {
                        type: 'number',
                        min: minRate,
                        max: maxRate,
                        message: `Rate must be between ${minRate}% and ${maxRate}%`
                      }
                    ]}
                  >
                    <InputNumber
                      prefix={<PercentageOutlined />}
                      suffix="%"
                      step={0.1}
                      style={{ width: '100%' }}
                      placeholder="Enter interest rate"
                    />
                  </Form.Item>
                </Col>

                <Col xs={24}>
                  <Form.Item label="Loan Term Unit">
                    <Radio.Group value={termUnit} onChange={e => setTermUnit(e.target.value)}>
                      <Radio.Button value="months">Months</Radio.Button>
                      <Radio.Button value="years">Years</Radio.Button>
                    </Radio.Group>
                  </Form.Item>
                </Col>

                <Col xs={24}>
                  <Form.Item
                    label={
                      <span>
                        Loan Term{' '}
                        <Tooltip title="The length of time to repay the loan">
                          <InfoCircleOutlined />
                        </Tooltip>
                      </span>
                    }
                    name="loan_term"
                    rules={[
                      { required: true, message: 'Loan term is required' },
                      {
                        type: 'number',
                        min: termUnit === 'months' ? minTermMonths : Math.ceil(minTermMonths / 12),
                        max: termUnit === 'months' ? maxTermMonths : Math.floor(maxTermMonths / 12),
                        message:
                          termUnit === 'months'
                            ? `Term must be between ${minTermMonths} and ${maxTermMonths} months`
                            : `Term must be between ${Math.ceil(minTermMonths / 12)} and ${Math.floor(maxTermMonths / 12)} years`
                      }
                    ]}
                  >
                    <InputNumber
                      prefix={<CalendarOutlined />}
                      suffix={termUnit}
                      style={{ width: '100%' }}
                      placeholder={`Enter term in ${termUnit}`}
                    />
                  </Form.Item>
                </Col>

                <Col xs={24}>
                  <Space size="middle" style={{ width: '100%', justifyContent: screens.xs ? 'stretch' : 'flex-start' }} wrap>
                    <Button
                      type="primary"
                      icon={<CalculatorOutlined />}
                      onClick={handleCalculate}
                      loading={calculating}
                      block={screens.xs}
                    >
                      Calculate
                    </Button>
                    <Button icon={<ReloadOutlined />} onClick={handleReset} block={screens.xs}>
                      Reset
                    </Button>
                  </Space>
                </Col>
              </Row>
            </Form>
          </Card>
        </Col>

        <Col xs={24} lg={12}>
          <Row gutter={[16, 16]}>
            <Col xs={24} sm={12} lg={24}>
              <StatCard
                title="Monthly Payment"
                value={calculationResult?.monthly_payment ?? 0}
                loading={calculating}
              />
            </Col>
            <Col xs={24} sm={12} lg={24}>
              <StatCard
                title="Total Interest Paid"
                value={calculationResult?.total_interest ?? 0}
                loading={calculating}
              />
            </Col>
            <Col xs={24} sm={12} lg={24}>
              <StatCard
                title="Total Amount Paid"
                value={calculationResult?.total_payment ?? 0}
                loading={calculating}
              />
            </Col>
          </Row>
        </Col>
      </Row>

      {calculationResult && (
        <Row gutter={[16, 16]} style={{ marginTop: 24 }}>
          <Col xs={24}>
            <Card title="Payment Breakdown" bordered={false}>
              <Row gutter={[16, 16]}>
                <Col xs={24} sm={12}>
                  <Statistic
                    title="Principal"
                    value={calculationResult.principal ?? 0}
                    prefix="$"
                    precision={2}
                    suffix={`(${principalPercentage}%)`}
                  />
                </Col>
                <Col xs={24} sm={12}>
                  <Statistic
                    title="Interest"
                    value={calculationResult.total_interest ?? 0}
                    prefix="$"
                    precision={2}
                    suffix={`(${interestPercentage}%)`}
                  />
                </Col>
              </Row>
            </Card>
          </Col>
        </Row>
      )}

      {calculationResult && (
        <Row gutter={[16, 16]} style={{ marginTop: 24 }}>
          <Col xs={24}>
            <Collapse
              activeKey={scheduleVisible ? ['schedule'] : []}
              onChange={keys => {
                const isOpen = (keys as string[]).includes('schedule');
                setScheduleVisible(isOpen);
                if (isOpen && scheduleData.length === 0) {
                  void handleGenerateSchedule();
                }
              }}
            >
              <Panel header="Show Amortization Schedule" key="schedule">
                <Space direction="vertical" size="middle" style={{ width: '100%' }}>
                  <Button
                    icon={<DownloadOutlined />}
                    onClick={handleExportCSV}
                    disabled={scheduleData.length === 0}
                    style={{ marginBottom: 16 }}
                  >
                    Export CSV
                  </Button>

                  <Table
                    columns={scheduleColumns}
                    dataSource={paginatedSchedule}
                    rowKey="payment_number"
                    loading={loadingSchedule}
                    scroll={{ x: 'max-content' }}
                    size={screens.xs ? 'small' : 'middle'}
                    pagination={{
                      current: schedulePage,
                      pageSize: schedulePageSize,
                      total: scheduleTotal,
                      onChange: (page, pageSize) => {
                        setSchedulePage(page);
                        setSchedulePageSize(pageSize ?? 20);
                      },
                      showSizeChanger: true,
                      showTotal: (total, range) => `${range[0]}-${range[1]} of ${total} payments`
                    }}
                    rowClassName={(record, index) => {
                      const globalIndex = (schedulePage - 1) * schedulePageSize + index;
                      return globalIndex === milestoneRowIndex ? 'milestone-row' : '';
                    }}
                  />
                </Space>
              </Panel>
            </Collapse>
          </Col>
        </Row>
      )}

      <Row gutter={[16, 16]} style={{ marginTop: 24 }}>
        <Col xs={24}>
          <Alert
            message="Disclaimer"
            description="These calculations are estimates for informational purposes only. Actual loan terms, interest rates, and monthly payments may vary based on your lender, creditworthiness, and other factors. Please consult with a financial advisor or lender for accurate loan information."
            type="info"
            showIcon
          />
        </Col>
      </Row>

      <style>{`
        .milestone-row {
          background-color: #e6f7ff !important;
          font-weight: 600;
        }
      `}</style>
    </div>
  );
};

export default LoanCalculatorPage;