import { useState, useMemo, useEffect, useCallback, CSSProperties } from 'react';
import { Card, Form, InputNumber, Button, Space, Typography, Tag, Progress, Alert, Table, List, Collapse, Modal, message, Radio } from 'antd';
import { CalculatorOutlined, DeleteOutlined } from '@ant-design/icons';
import { request } from '../api/network';
import { useAppContext } from '../context/AppContext';

type HeightUnit = 'CM' | 'METERS' | 'FEET' | 'INCHES' | 'FEET_INCHES';
type WeightUnit = 'KG' | 'LBS';

interface BmiCategoryResponse {
  id: string;
  name: string;
  min_bmi: number;
  max_bmi: number | null;
  description: string | null;
  color_code: string | null;
  created_at: string;
  updated_at: string;
}

interface CalculationListItemResponse {
  id: string;
  height: number;
  weight: number;
  height_unit: string;
  weight_unit: string;
  bmi_value: number;
  timestamp: string;
  bmi_category_name: string;
  bmi_category_color_code: string | null;
}

interface ComputeBMIResponse {
  id: string;
  height: number;
  weight: number;
  height_unit: string;
  weight_unit: string;
  bmi_value: number;
  bmi_category_id: string;
  bmi_category_name: string;
  bmi_category_description: string | null;
  bmi_category_color_code: string | null;
  bmi_category_min_bmi: number;
  bmi_category_max_bmi: number | null;
  timestamp: string;
}

export default function BmiCalculatorPage() {
  const [messageApi, contextHolder] = message.useMessage();
  const [form] = Form.useForm();
  const { sessionId, unitSystem, setUnitSystem } = useAppContext();

  const [bmiResult, setBmiResult] = useState<ComputeBMIResponse | null>(null);
  const [calculations, setCalculations] = useState<CalculationListItemResponse[]>([]);
  const [bmiCategories, setBmiCategories] = useState<BmiCategoryResponse[]>([]);
  const [isCalculating, setIsCalculating] = useState(false);
  const [showClearHistoryConfirm, setShowClearHistoryConfirm] = useState(false);
  const [infoCollapsed, setInfoCollapsed] = useState(true);

  const hasResult = useMemo(() => bmiResult !== null, [bmiResult]);
  const hasHistory = useMemo(() => calculations.length > 0, [calculations.length]);
  const sortedCalculations = useMemo(() => {
    return [...calculations].sort((a, b) => new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime());
  }, [calculations]);

  const fetchBmiCategories = useCallback(async () => {
    try {
      const result = await request<BmiCategoryResponse[]>({
        method: 'GET',
        path: '/bmi-management/bmi-categories',
        query: { limit: 50, offset: 0 }
      });
      setBmiCategories(result.data);
    } catch (error) {
      messageApi.error('Failed to load BMI categories');
    }
  }, [messageApi]);

  const fetchCalculationHistory = useCallback(async () => {
    try {
      const result = await request<CalculationListItemResponse[]>({
        method: 'GET',
        path: '/bmi-management/calculations',
        query: { limit: 50, offset: 0, session_id: sessionId || '' }
      });
      setCalculations(result.data);
    } catch (error) {
      messageApi.error('Failed to load calculation history');
    }
  }, [messageApi, sessionId]);

  useEffect(() => {
    fetchBmiCategories();
    fetchCalculationHistory();
  }, [fetchBmiCategories, fetchCalculationHistory]);

  const calculateBmi = useCallback(async () => {
    try {
      const formValues = await form.validateFields();
      
      if (!formValues.height || formValues.height <= 0) {
        messageApi.error('Height must be greater than 0');
        return;
      }
      if (!formValues.weight || formValues.weight <= 0) {
        messageApi.error('Weight must be greater than 0');
        return;
      }

      setIsCalculating(true);

      const heightUnit: HeightUnit = unitSystem === 'metric' ? 'CM' : 'INCHES';
      const weightUnit: WeightUnit = unitSystem === 'metric' ? 'KG' : 'LBS';

      const result = await request<ComputeBMIResponse>({
        method: 'POST',
        path: '/bmi-management/calculations/compute',
        body: {
          height: formValues.height,
          weight: formValues.weight,
          height_unit: heightUnit,
          weight_unit: weightUnit,
          session_id: sessionId || null
        }
      });

      setBmiResult(result.data);
      messageApi.success('BMI calculated successfully!');
      await fetchCalculationHistory();
    } catch (error) {
      messageApi.error('Failed to calculate BMI. Please check your inputs.');
    } finally {
      setIsCalculating(false);
    }
  }, [form, messageApi, unitSystem, sessionId, fetchCalculationHistory]);

  const clearForm = useCallback(() => {
    setBmiResult(null);
    form.resetFields();
  }, [form]);

  const showClearHistoryDialog = useCallback(() => {
    setShowClearHistoryConfirm(true);
  }, []);

  const confirmClearHistory = useCallback(async () => {
    try {
      await request({
        method: 'DELETE',
        path: '/bmi-management/calculations',
        query: { session_id: sessionId || '' }
      });
      setCalculations([]);
      setShowClearHistoryConfirm(false);
      messageApi.success('Calculation history cleared.');
    } catch (error) {
      messageApi.error('Failed to clear history.');
    }
  }, [messageApi, sessionId]);

  const cancelClearHistory = useCallback(() => {
    setShowClearHistoryConfirm(false);
  }, []);

  const onUnitSystemChange = useCallback((e: { target: { value: string } }) => {
    setUnitSystem(e.target.value as 'metric' | 'imperial');
  }, [setUnitSystem]);

  const categoryTableColumns = useMemo(() => [
    {
      title: 'Category',
      dataIndex: 'name',
      key: 'name'
    },
    {
      title: 'BMI Range',
      key: 'range',
      render: (_: unknown, record: BmiCategoryResponse) => {
        const maxBmi = record.max_bmi !== null ? record.max_bmi.toFixed(1) : '∞';
        return `${record.min_bmi.toFixed(1)} - ${maxBmi}`;
      }
    },
    {
      title: 'Color',
      dataIndex: 'color_code',
      key: 'color_code',
      render: (color: string | null) => (
        color ? <div style={{ width: 24, height: 24, backgroundColor: color, borderRadius: 4, border: '1px solid #d9d9d9' }} /> : null
      )
    }
  ], []);

  const mainContainerStyle: CSSProperties = {
    minHeight: '100vh',
    height: '100%',
    width: '100%',
    display: 'flex',
    flexDirection: 'column',
    padding: '24px',
    maxWidth: '900px',
    margin: '0 auto'
  };

  const heightUnit = unitSystem === 'metric' ? 'cm' : 'in';
  const weightUnit = unitSystem === 'metric' ? 'kg' : 'lbs';

  return (
    <div style={mainContainerStyle}>
      {contextHolder}
      
      <Typography.Title level={2} style={{ textAlign: 'center', marginBottom: '8px' }}>
        BMI Calculator
      </Typography.Title>
      
      <Typography.Text type="secondary" style={{ display: 'block', textAlign: 'center', marginBottom: '24px' }}>
        Calculate your Body Mass Index and track your health
      </Typography.Text>

      <Card title="Calculate Your BMI" bordered style={{ marginBottom: '24px' }}>
        <Form form={form} layout="vertical" name="bmi_form" onFinish={calculateBmi}>
          <Form.Item label="Unit System" name="unit_system">
            <Radio.Group
              value={unitSystem}
              onChange={onUnitSystemChange}
              optionType="button"
              buttonStyle="solid"
              options={[
                { label: 'Metric (cm/kg)', value: 'metric' },
                { label: 'Imperial (in/lbs)', value: 'imperial' }
              ]}
            />
          </Form.Item>

          <Form.Item
            label="Height"
            name="height"
            rules={[
              { required: true, message: 'Please enter your height' },
              { type: 'number', min: 1, message: 'Height must be greater than 0' }
            ]}
          >
            <InputNumber
              placeholder="Enter height"
              min={1}
              max={300}
              precision={2}
              style={{ width: '100%' }}
              addonAfter={heightUnit}
              aria-label="Height input"
            />
          </Form.Item>

          <Form.Item
            label="Weight"
            name="weight"
            rules={[
              { required: true, message: 'Please enter your weight' },
              { type: 'number', min: 1, message: 'Weight must be greater than 0' }
            ]}
          >
            <InputNumber
              placeholder="Enter weight"
              min={1}
              max={500}
              precision={2}
              style={{ width: '100%' }}
              addonAfter={weightUnit}
              aria-label="Weight input"
            />
          </Form.Item>

          <Space size="middle" style={{ marginTop: '16px' }}>
            <Button
              type="primary"
              htmlType="submit"
              size="large"
              icon={<CalculatorOutlined />}
              loading={isCalculating}
              aria-label="Calculate BMI"
            >
              Calculate BMI
            </Button>
            <Button size="large" onClick={clearForm} aria-label="Clear form">
              Clear
            </Button>
          </Space>
        </Form>
      </Card>

      {hasResult && bmiResult && (
        <Card title="Your BMI Result" bordered style={{ marginBottom: '24px' }}>
          <div style={{ textAlign: 'center', padding: '16px' }}>
            <Typography.Title
              level={1}
              style={{ fontSize: '48px', marginBottom: '8px' }}
              aria-label="BMI result value"
            >
              {bmiResult.bmi_value.toFixed(1)}
            </Typography.Title>

            <Tag
              color={bmiResult.bmi_category_color_code || undefined}
              style={{ fontSize: '18px', padding: '8px 16px' }}
            >
              {bmiResult.bmi_category_name}
            </Tag>

            <div style={{ margin: '24px 0', padding: '16px' }}>
              <Progress
                type="dashboard"
                percent={Math.min((bmiResult.bmi_value / 40) * 100, 100)}
                format={() => 'BMI Scale'}
                strokeColor={{
                  '0%': '#3498db',
                  '33%': '#2ecc71',
                  '66%': '#f39c12',
                  '100%': '#e74c3c'
                }}
              />
            </div>

            {bmiResult.bmi_category_description && (
              <Typography.Paragraph style={{ marginTop: '16px', fontSize: '14px' }}>
                {bmiResult.bmi_category_description}
              </Typography.Paragraph>
            )}

            <Alert
              message="Disclaimer"
              description="BMI is a general indicator and does not account for muscle mass, bone density, or overall body composition. Please consult a healthcare professional for personalized health advice."
              type="info"
              showIcon
              style={{ marginTop: '16px' }}
            />
          </div>
        </Card>
      )}

      <Card title="BMI Category Reference" bordered style={{ marginBottom: '24px' }}>
        <Table
          dataSource={bmiCategories}
          columns={categoryTableColumns}
          pagination={false}
          size="small"
          rowKey="id"
        />
      </Card>

      <Card title="Calculation History" bordered style={{ marginBottom: '24px' }}>
        <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: '16px' }}>
          <Typography.Text type="secondary">
            {calculations.length} calculation{calculations.length !== 1 ? 's' : ''}
          </Typography.Text>
          {hasHistory && (
            <Button
              danger
              size="small"
              icon={<DeleteOutlined />}
              onClick={showClearHistoryDialog}
              aria-label="Clear calculation history"
            >
              Clear History
            </Button>
          )}
        </div>

        <List
          size="small"
          bordered
          dataSource={sortedCalculations}
          locale={{ emptyText: 'No calculations yet. Calculate your BMI to see history here.' }}
          aria-label="Calculation history list"
          renderItem={(item) => (
            <List.Item>
              <div style={{ width: '100%' }}>
                <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
                  <div>
                    <strong>BMI: {item.bmi_value.toFixed(1)}</strong>
                    <Tag
                      color={item.bmi_category_color_code || undefined}
                      style={{ marginLeft: 8 }}
                    >
                      {item.bmi_category_name}
                    </Tag>
                  </div>
                  <Typography.Text type="secondary" style={{ fontSize: '12px' }}>
                    {new Date(item.timestamp).toLocaleString()}
                  </Typography.Text>
                </div>
                <Typography.Text type="secondary" style={{ fontSize: '12px' }}>
                  Height: {item.height.toFixed(1)} {item.height_unit.toLowerCase()} | Weight: {item.weight.toFixed(1)} {item.weight_unit.toLowerCase()}
                </Typography.Text>
              </div>
            </List.Item>
          )}
        />
      </Card>

      <Collapse
        bordered
        style={{ marginBottom: '24px' }}
        items={[
          {
            key: 'bmi_info',
            label: 'What is BMI?',
            children: (
              <Typography.Paragraph>
                Body Mass Index (BMI) is a simple calculation using a person's height and weight. The BMI value categorizes a person as underweight, normal weight, overweight, or obese. It is widely used as a general indicator of whether a person has a healthy body weight for their height.
              </Typography.Paragraph>
            )
          },
          {
            key: 'formula',
            label: 'BMI Formula',
            children: (
              <Typography.Paragraph>
                BMI = weight (kg) / [height (m)]². For example, if you weigh 70 kg and are 1.75 m tall: BMI = 70 / (1.75)² = 70 / 3.0625 = 22.9
              </Typography.Paragraph>
            )
          },
          {
            key: 'limitations',
            label: 'Limitations of BMI',
            children: (
              <Typography.Paragraph>
                BMI does not distinguish between muscle and fat mass. Athletes may have a high BMI due to increased muscle mass. BMI also does not account for age, sex, ethnicity, or body fat distribution. It should be used as a screening tool, not a diagnostic measure.
              </Typography.Paragraph>
            )
          },
          {
            key: 'measurement_tips',
            label: 'Measurement Guidelines',
            children: (
              <Typography.Paragraph>
                For accurate results: Measure height without shoes, standing straight against a wall. Measure weight in the morning before eating, wearing light clothing. Use a calibrated scale on a hard, flat surface.
              </Typography.Paragraph>
            )
          }
        ]}
      />

      <Modal
        title="Clear Calculation History"
        open={showClearHistoryConfirm}
        onOk={confirmClearHistory}
        onCancel={cancelClearHistory}
        okText="Yes, Clear All"
        cancelText="Cancel"
        okButtonProps={{ danger: true }}
      >
        <Typography.Paragraph>
          Are you sure you want to clear all calculation history? This action cannot be undone.
        </Typography.Paragraph>
      </Modal>
    </div>
  );
}