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

interface BmiCategory {
  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 CalculationDetail {
  id: string;
  height: number;
  weight: number;
  height_unit: string;
  weight_unit: string;
  bmi_value: number;
  bmi_category_id: string;
  session_id: string | null;
  timestamp: string;
  created_at: string;
  updated_at: string;
  bmi_category: BmiCategory;
}

interface CalculateRequestBody {
  height: number;
  weight: number;
  height_unit: string;
  weight_unit: string;
  session_id: string | null;
}

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

  const [bmiResult, setBmiResult] = useState<CalculationDetail | null>(null);
  const [calculations, setCalculations] = useState<CalculationDetail[]>([]);
  const [bmiCategories, setBmiCategories] = useState<BmiCategory[]>([]);
  const [isCalculating, setIsCalculating] = useState<boolean>(false);
  const [showResult, setShowResult] = useState<boolean>(false);
  const [confirmClearVisible, setConfirmClearVisible] = useState<boolean>(false);
  const [infoCollapsed, setInfoCollapsed] = useState<boolean>(true);

  const sortedCalculations = useMemo(() => {
    return calculations.slice().sort((a, b) => new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime());
  }, [calculations]);

  const hasHistory = useMemo(() => {
    return calculations.length > 0;
  }, [calculations]);

  const categoryTableColumns = useMemo(() => [
    {
      title: 'Category',
      dataIndex: 'name',
      key: 'name',
      render: (name: string) => name.replace(/_/g, ' ')
    },
    {
      title: 'BMI Range',
      key: 'range',
      render: (_: unknown, record: BmiCategory) => {
        if (record.max_bmi === null) {
          return `≥ ${record.min_bmi}`;
        }
        return `${record.min_bmi} - ${record.max_bmi}`;
      }
    },
    {
      title: 'Color',
      dataIndex: 'color_code',
      key: 'color_code',
      render: (color: string | null) => (
        <div style={{ display: 'flex', alignItems: 'center', gap: '8px' }}>
          <div style={{ width: '20px', height: '20px', backgroundColor: color || '#ccc', borderRadius: '4px' }} />
          <span>{color || 'N/A'}</span>
        </div>
      )
    }
  ], []);

  const fetchBmiCategories = useCallback(async () => {
    try {
      const result = await request<BmiCategory[]>({
        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 fetchHistory = useCallback(async () => {
    try {
      const result = await request<CalculationDetail[]>({
        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();
    fetchHistory();
  }, [fetchBmiCategories, fetchHistory]);

  const calculateBmi = useCallback(async () => {
    try {
      const values = await form.validateFields();
      
      if (!values.height || values.height < 1) {
        messageApi.error('Height must be a positive number');
        return;
      }
      if (!values.weight || values.weight < 1) {
        messageApi.error('Weight must be a positive number');
        return;
      }

      setIsCalculating(true);
      setShowResult(true);

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

      const body: CalculateRequestBody = {
        height: values.height,
        weight: values.weight,
        height_unit: heightUnit,
        weight_unit: weightUnit,
        session_id: sessionId
      };

      const result = await request<CalculationDetail>({
        method: 'POST',
        path: '/bmi-management/calculations/calculate',
        body
      });

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

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

  const showClearConfirm = useCallback(() => {
    setConfirmClearVisible(true);
  }, []);

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

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

  const onUnitSystemChange = useCallback((e: { target: { value: string } }) => {
    const newValue = e.target.value;
  }, []);

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

  const pageTitleStyle: CSSProperties = {
    textAlign: 'center',
    marginBottom: '8px'
  };

  const pageSubtitleStyle: CSSProperties = {
    textAlign: 'center',
    display: 'block',
    marginBottom: '24px'
  };

  const inputCardStyle: CSSProperties = {
    marginBottom: '24px'
  };

  const unitToggleStyle: CSSProperties = {
    marginBottom: '16px',
    display: 'block'
  };

  const heightInputRowStyle: CSSProperties = {
    display: 'flex',
    gap: '16px',
    flexWrap: 'wrap'
  };

  const heightInputStyle: CSSProperties = {
    flex: '1',
    minWidth: '200px'
  };

  const weightInputStyle: CSSProperties = {
    flex: '1',
    minWidth: '200px'
  };

  const buttonRowStyle: CSSProperties = {
    display: 'flex',
    gap: '12px',
    marginTop: '16px'
  };

  const calculateButtonStyle: CSSProperties = {
    flex: '1'
  };

  const resultCardStyle: CSSProperties = {
    marginBottom: '24px'
  };

  const resultContainerStyle: CSSProperties = {
    textAlign: 'center',
    padding: '16px'
  };

  const bmiValueDisplayStyle: CSSProperties = {
    fontSize: '48px',
    marginBottom: '8px',
    color: '#2ecc71'
  };

  const bmiCategoryBadgeStyle: CSSProperties = {
    marginBottom: '16px'
  };

  const bmiGaugeContainerStyle: CSSProperties = {
    marginTop: '16px',
    marginBottom: '16px'
  };

  const bmiGaugeBarStyle: CSSProperties = {
    marginBottom: '8px'
  };

  const gaugeLabelsStyle: CSSProperties = {
    display: 'flex',
    justifyContent: 'space-between',
    fontSize: '12px'
  };

  const healthInfoTextStyle: CSSProperties = {
    marginTop: '16px',
    textAlign: 'left'
  };

  const disclaimerAlertStyle: CSSProperties = {
    marginTop: '16px'
  };

  const categoryReferenceCardStyle: CSSProperties = {
    marginBottom: '24px'
  };

  const historyCardStyle: CSSProperties = {
    marginBottom: '24px'
  };

  const historyHeaderStyle: CSSProperties = {
    display: 'flex',
    justifyContent: 'space-between',
    alignItems: 'center',
    marginBottom: '16px'
  };

  const infoCollapseCardStyle: CSSProperties = {
    marginBottom: '24px'
  };

  const bmiInfoContentStyle: CSSProperties = {
    padding: '8px'
  };

  const infoCategoriesTitleStyle: CSSProperties = {
    marginTop: '12px'
  };

  const infoLimitationsTitleStyle: CSSProperties = {
    marginTop: '12px'
  };

  const infoMeasurementTitleStyle: CSSProperties = {
    marginTop: '12px'
  };

  return (
    <div style={mainContainerStyle}>
      {contextHolder}
      <Typography.Title level={2} style={pageTitleStyle}>
        BMI Calculator
      </Typography.Title>
      <Typography.Text type="secondary" style={pageSubtitleStyle}>
        Calculate your Body Mass Index and track your health
      </Typography.Text>

      <Card title="Calculate Your BMI" style={inputCardStyle}>
        <Radio.Group
          value={unitSystem}
          onChange={onUnitSystemChange}
          optionType="button"
          buttonStyle="solid"
          style={unitToggleStyle}
          options={[
            { label: 'Metric (cm/kg)', value: 'metric' },
            { label: 'Imperial (ft-in/lbs)', value: 'imperial' }
          ]}
        />
        <Form form={form} layout="vertical" name="bmi_form" onFinish={calculateBmi}>
          <div style={heightInputRowStyle}>
            <Form.Item
              name="height"
              label="Height"
              rules={[
                { required: true, message: 'Please enter your height' },
                { type: 'number', min: 1, message: 'Height must be positive' }
              ]}
              tooltip="Enter height in cm (metric) or inches (imperial)"
              style={heightInputStyle}
            >
              <InputNumber
                placeholder="e.g. 170 cm or 67 inches"
                min={1}
                max={300}
                step={0.1}
                style={{ width: '100%' }}
                addonAfter="cm / in"
              />
            </Form.Item>
            <Form.Item
              name="weight"
              label="Weight"
              rules={[
                { required: true, message: 'Please enter your weight' },
                { type: 'number', min: 1, message: 'Weight must be positive' }
              ]}
              tooltip="Enter weight in kg (metric) or lbs (imperial)"
              style={weightInputStyle}
            >
              <InputNumber
                placeholder="e.g. 70 kg or 154 lbs"
                min={1}
                max={500}
                step={0.1}
                style={{ width: '100%' }}
                addonAfter="kg / lbs"
              />
            </Form.Item>
          </div>
          <div style={buttonRowStyle}>
            <Button
              type="primary"
              size="large"
              htmlType="submit"
              icon={<CalculatorOutlined />}
              loading={isCalculating}
              style={calculateButtonStyle}
            >
              Calculate BMI
            </Button>
            <Button size="large" onClick={clearForm}>
              Clear
            </Button>
          </div>
        </Form>
      </Card>

      {showResult && bmiResult && (
        <Card title="Your BMI Result" style={resultCardStyle}>
          <div style={resultContainerStyle}>
            <Typography.Title level={1} style={bmiValueDisplayStyle}>
              {bmiResult.bmi_value.toFixed(1)}
            </Typography.Title>
            <Tag
              color={bmiResult.bmi_category.color_code || 'green'}
              style={{ fontSize: '16px', padding: '4px 16px', ...bmiCategoryBadgeStyle }}
            >
              {bmiResult.bmi_category.name.replace(/_/g, ' ')}
            </Tag>
            <div style={bmiGaugeContainerStyle}>
              <Progress
                percent={Math.min((bmiResult.bmi_value / 40) * 100, 100)}
                showInfo={false}
                strokeColor={{ from: '#3498db', to: '#e74c3c' }}
                style={bmiGaugeBarStyle}
              />
              <div style={gaugeLabelsStyle}>
                <Typography.Text type="secondary" style={{ color: '#3498db' }}>
                  Underweight (&lt;18.5)
                </Typography.Text>
                <Typography.Text type="secondary" style={{ color: '#2ecc71' }}>
                  Normal (18.5-24.9)
                </Typography.Text>
                <Typography.Text type="secondary" style={{ color: '#f39c12' }}>
                  Overweight (25-29.9)
                </Typography.Text>
                <Typography.Text type="secondary" style={{ color: '#e74c3c' }}>
                  Obese (≥30)
                </Typography.Text>
              </div>
            </div>
            {bmiResult.bmi_category.description && (
              <Typography.Paragraph style={healthInfoTextStyle}>
                {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={disclaimerAlertStyle}
            />
          </div>
        </Card>
      )}

      <Card title="BMI Category Reference" style={categoryReferenceCardStyle}>
        <Table
          dataSource={bmiCategories}
          columns={categoryTableColumns}
          pagination={false}
          size="small"
          rowKey="id"
        />
      </Card>

      <Card title="Calculation History" style={historyCardStyle}>
        <div style={historyHeaderStyle}>
          <Typography.Text strong>Past Calculations</Typography.Text>
          {hasHistory && (
            <Button danger size="small" icon={<DeleteOutlined />} onClick={showClearConfirm}>
              Clear History
            </Button>
          )}
        </div>
        {hasHistory ? (
          <List
            size="small"
            bordered
            dataSource={sortedCalculations}
            renderItem={(item) => (
              <List.Item>
                <div style={{ width: '100%' }}>
                  <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
                    <div>
                      <Typography.Text strong>BMI: {item.bmi_value.toFixed(1)}</Typography.Text>
                      <Tag color={item.bmi_category.color_code || 'default'} style={{ marginLeft: '8px' }}>
                        {item.bmi_category.name.replace(/_/g, ' ')}
                      </Tag>
                    </div>
                    <Typography.Text type="secondary">
                      {new Date(item.timestamp).toLocaleString()}
                    </Typography.Text>
                  </div>
                  <Typography.Text type="secondary" style={{ fontSize: '12px' }}>
                    Height: {item.height} {item.height_unit} | Weight: {item.weight} {item.weight_unit}
                  </Typography.Text>
                </div>
              </List.Item>
            )}
          />
        ) : (
          <Empty description="No calculations yet. Calculate your BMI to see history here." style={{ padding: '24px' }} />
        )}
      </Card>

      <Collapse
        items={[
          {
            key: 'bmi_info',
            label: 'BMI Information & Guidelines',
            children: (
              <div style={bmiInfoContentStyle}>
                <Typography.Title level={5}>BMI Formula</Typography.Title>
                <Typography.Paragraph>
                  BMI = Weight (kg) ÷ Height (m)². For imperial units, the formula is: BMI = (Weight in lbs × 703) ÷ (Height in inches)².
                </Typography.Paragraph>
                <Typography.Title level={5} style={infoCategoriesTitleStyle}>
                  Category Ranges (WHO Standards)
                </Typography.Title>
                <Typography.Paragraph>
                  Underweight: BMI &lt; 18.5 | Normal weight: 18.5–24.9 | Overweight: 25.0–29.9 | Obese: BMI ≥ 30.0
                </Typography.Paragraph>
                <Typography.Title level={5} style={infoLimitationsTitleStyle}>
                  Limitations of BMI
                </Typography.Title>
                <Typography.Paragraph>
                  BMI does not distinguish between muscle and fat mass. Athletes may have a high BMI due to muscle. BMI may not be accurate for elderly, pregnant women, or growing children. It does not account for bone density, ethnicity, or fat distribution.
                </Typography.Paragraph>
                <Typography.Title level={5} style={infoMeasurementTitleStyle}>
                  Measurement Guidelines
                </Typography.Title>
                <Typography.Paragraph>
                  Measure height without shoes, standing straight against a wall. Weigh yourself in the morning before eating, wearing light clothing. Use consistent units for accurate tracking over time.
                </Typography.Paragraph>
              </div>
            )
          }
        ]}
        bordered
        style={infoCollapseCardStyle}
      />

      <Modal
        title="Clear Calculation History"
        open={confirmClearVisible}
        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>
  );
}