import { useState, useMemo, useEffect, useCallback, CSSProperties } from 'react';
import { Button, Card, Typography, Drawer, List, Tooltip, message, Modal } from 'antd';
import { ClockCircleOutlined, CopyOutlined, DeleteOutlined } from '@ant-design/icons';
import { useAppContext } from '@/store/AppStore';
import { CalculatorService } from '@/services/calculator';
import { parseError } from '@/utils/errorHandler';

interface SessionHistoryResponse {
  id: string;
  session_id: string;
  start_time: string;
  last_activity_time: string;
  created_at: string;
  updated_at: string;
}

interface CalculationResponse {
  id: string;
  session_history_id: string;
  operand1: number;
  operator: string;
  operand2: number;
  result: number;
  expression: string;
  timestamp: string;
  created_at: string;
  updated_at: string;
}

interface CalculatorStateResponse {
  id: string;
  session_history_id: string;
  current_display: string;
  previous_value: number | null;
  current_operator: string | null;
  awaiting_operand: boolean;
  is_result_displayed: boolean;
  memory: number;
  created_at: string;
  updated_at: string;
}

const CalculatorPage = () => {
  const [messageApi, contextHolder] = message.useMessage();
  const { calculatorState, sessionHistory, setCalculatorState, setSessionHistory } = useAppContext();

  const [sessionHistoryId, setSessionHistoryId] = useState<string | null>(null);
  const [calculatorStateId, setCalculatorStateId] = useState<string | null>(null);
  const [historyDrawerVisible, setHistoryDrawerVisible] = useState<boolean>(false);
  const [loading, setLoading] = useState<boolean>(false);
  const [errorState, setErrorState] = useState<boolean>(false);
  const [copyTooltipVisible, setCopyTooltipVisible] = useState<boolean>(false);

  const hasMemoryValue = useMemo(() => {
    return calculatorState.memory !== 0;
  }, [calculatorState.memory]);

  const displayExpression = useMemo(() => {
    if (calculatorState.previousValue !== null && calculatorState.currentOperator !== null) {
      return String(calculatorState.previousValue) + ' ' + calculatorState.currentOperator + ' ';
    }
    return '';
  }, [calculatorState.previousValue, calculatorState.currentOperator]);

  const formattedHistory = useMemo(() => {
    return sessionHistory.slice().reverse().slice(0, 50);
  }, [sessionHistory]);

  const initializeSession = useCallback(async () => {
    try {
      setLoading(true);
      const sessionId = `session_${Date.now()}`;
      const now = new Date().toISOString();
      const { data: sessionData } = await CalculatorService.createSessionHistory({
        session_id: sessionId,
        start_time: now,
        last_activity_time: now,
      });
      setSessionHistoryId(sessionData.id);

      const { data: stateData } = await CalculatorService.createCalculatorState({
        session_history_id: sessionData.id,
        current_display: '0',
        previous_value: null,
        current_operator: null,
        awaiting_operand: false,
        is_result_displayed: false,
        memory: 0,
      });
      setCalculatorStateId(stateData.id);
      setCalculatorState({
        currentDisplay: stateData.current_display,
        previousValue: stateData.previous_value,
        currentOperator: stateData.current_operator,
        awaitingOperand: stateData.awaiting_operand,
        isResultDisplayed: stateData.is_result_displayed,
        memory: stateData.memory,
      });
    } catch (e) {
      const { message: errorMessage } = parseError(e);
      messageApi.error(errorMessage || 'Failed to initialize session');
    } finally {
      setLoading(false);
    }
  }, [messageApi, setCalculatorState]);

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

  const handleDigitPress = useCallback((digit: number) => {
    const newDisplay = calculatorState.awaitingOperand || calculatorState.isResultDisplayed
      ? String(digit)
      : calculatorState.currentDisplay === '0'
      ? String(digit)
      : calculatorState.currentDisplay + String(digit);

    setCalculatorState({
      ...calculatorState,
      currentDisplay: newDisplay,
      awaitingOperand: false,
      isResultDisplayed: false,
    });
  }, [calculatorState, setCalculatorState]);

  const handleOperatorPress = useCallback((operator: string) => {
    setCalculatorState({
      ...calculatorState,
      previousValue: parseFloat(calculatorState.currentDisplay),
      currentOperator: operator,
      awaitingOperand: true,
      isResultDisplayed: false,
    });
  }, [calculatorState, setCalculatorState]);

  const handleDecimalPress = useCallback(() => {
    if (!calculatorState.currentDisplay.includes('.')) {
      setCalculatorState({
        ...calculatorState,
        currentDisplay: calculatorState.currentDisplay + '.',
      });
    }
  }, [calculatorState, setCalculatorState]);

  const handleToggleSign = useCallback(() => {
    const newDisplay = calculatorState.currentDisplay.startsWith('-')
      ? calculatorState.currentDisplay.slice(1)
      : '-' + calculatorState.currentDisplay;

    setCalculatorState({
      ...calculatorState,
      currentDisplay: newDisplay,
    });
  }, [calculatorState, setCalculatorState]);

  const handleBackspace = useCallback(() => {
    const newDisplay = calculatorState.currentDisplay.length <= 1
      ? '0'
      : calculatorState.currentDisplay.slice(0, -1);

    setCalculatorState({
      ...calculatorState,
      currentDisplay: newDisplay,
    });
  }, [calculatorState, setCalculatorState]);

  const handlePercentage = useCallback(() => {
    const newDisplay = String(parseFloat(calculatorState.currentDisplay) / 100);
    setCalculatorState({
      ...calculatorState,
      currentDisplay: newDisplay,
    });
  }, [calculatorState, setCalculatorState]);

  const pressEquals = useCallback(async () => {
    if (!sessionHistoryId || calculatorState.previousValue === null || !calculatorState.currentOperator) {
      return;
    }

    try {
      const { data: calcResult } = await CalculatorService.performCalculation(sessionHistoryId, {
        operand1: calculatorState.previousValue,
        operator: calculatorState.currentOperator,
        operand2: parseFloat(calculatorState.currentDisplay),
      });

      setCalculatorState({
        ...calculatorState,
        currentDisplay: String(calcResult.result),
        isResultDisplayed: true,
        previousValue: null,
        currentOperator: null,
        awaitingOperand: false,
      });

      setSessionHistory([...sessionHistory, calcResult]);
    } catch (e) {
      const { message: errorMessage } = parseError(e);
      messageApi.error(errorMessage || 'Calculation error');
    }
  }, [sessionHistoryId, calculatorState, sessionHistory, setCalculatorState, setSessionHistory, messageApi]);

  const pressClearEntry = useCallback(async () => {
    if (!calculatorStateId) return;

    try {
      await CalculatorService.clearEntry(calculatorStateId);
      setCalculatorState({
        ...calculatorState,
        currentDisplay: '0',
      });
    } catch (e) {
      const { message: errorMessage } = parseError(e);
      messageApi.error(errorMessage);
    }
  }, [calculatorStateId, calculatorState, setCalculatorState, messageApi]);

  const pressAllClear = useCallback(async () => {
    if (!calculatorStateId) return;

    try {
      await CalculatorService.allClear(calculatorStateId);
      setCalculatorState({
        currentDisplay: '0',
        previousValue: null,
        currentOperator: null,
        awaitingOperand: false,
        isResultDisplayed: false,
        memory: calculatorState.memory,
      });
      setErrorState(false);
    } catch (e) {
      const { message: errorMessage } = parseError(e);
      messageApi.error(errorMessage);
    }
  }, [calculatorStateId, calculatorState.memory, setCalculatorState, messageApi]);

  const pressMemoryClear = useCallback(async () => {
    if (!calculatorStateId) return;

    try {
      await CalculatorService.memoryClear(calculatorStateId);
      setCalculatorState({
        ...calculatorState,
        memory: 0,
      });
    } catch (e) {
      const { message: errorMessage } = parseError(e);
      messageApi.error(errorMessage);
    }
  }, [calculatorStateId, calculatorState, setCalculatorState, messageApi]);

  const pressMemoryRecall = useCallback(async () => {
    if (!calculatorStateId) return;

    try {
      await CalculatorService.memoryRecall(calculatorStateId);
      setCalculatorState({
        ...calculatorState,
        currentDisplay: String(calculatorState.memory),
      });
    } catch (e) {
      const { message: errorMessage } = parseError(e);
      messageApi.error(errorMessage);
    }
  }, [calculatorStateId, calculatorState, setCalculatorState, messageApi]);

  const pressMemoryAdd = useCallback(async () => {
    if (!calculatorStateId) return;

    try {
      await CalculatorService.memoryAdd(calculatorStateId);
      setCalculatorState({
        ...calculatorState,
        memory: calculatorState.memory + parseFloat(calculatorState.currentDisplay),
      });
    } catch (e) {
      const { message: errorMessage } = parseError(e);
      messageApi.error(errorMessage);
    }
  }, [calculatorStateId, calculatorState, setCalculatorState, messageApi]);

  const pressMemorySubtract = useCallback(async () => {
    if (!calculatorStateId) return;

    try {
      await CalculatorService.memorySubtract(calculatorStateId);
      setCalculatorState({
        ...calculatorState,
        memory: calculatorState.memory - parseFloat(calculatorState.currentDisplay),
      });
    } catch (e) {
      const { message: errorMessage } = parseError(e);
      messageApi.error(errorMessage);
    }
  }, [calculatorStateId, calculatorState, setCalculatorState, messageApi]);

  const copyResult = useCallback(async () => {
    try {
      await navigator.clipboard.writeText(calculatorState.currentDisplay);
      setCopyTooltipVisible(true);
      messageApi.success('Copied!');
      setTimeout(() => setCopyTooltipVisible(false), 2000);
    } catch (e) {
      const { message: errorMessage } = parseError(e);
      messageApi.error(errorMessage || 'Failed to copy');
    }
  }, [calculatorState.currentDisplay, messageApi]);

  const openHistoryDrawer = useCallback(async () => {
    if (!sessionHistoryId) return;

    try {
      setLoading(true);
      const { data: historyData } = await CalculatorService.getSessionCalculations(sessionHistoryId, { limit: 50 });
      setSessionHistory(historyData);
      setHistoryDrawerVisible(true);
    } catch (e) {
      const { message: errorMessage } = parseError(e);
      messageApi.error(errorMessage || 'Failed to load history');
    } finally {
      setLoading(false);
    }
  }, [sessionHistoryId, setSessionHistory, messageApi]);

  const closeHistoryDrawer = useCallback(() => {
    setHistoryDrawerVisible(false);
  }, []);

  const clearSessionHistory = useCallback(async () => {
    if (!sessionHistoryId) return;

    Modal.confirm({
      title: 'Clear History',
      content: 'Are you sure you want to clear all calculation history?',
      okText: 'Clear',
      okType: 'danger',
      cancelText: 'Cancel',
      onOk: async () => {
        try {
          setLoading(true);
          await CalculatorService.clearSessionHistory(sessionHistoryId);
          setSessionHistory([]);
          messageApi.success('History cleared');
        } catch (e) {
          const { message: errorMessage } = parseError(e);
          messageApi.error(errorMessage || 'Failed to clear history');
        } finally {
          setLoading(false);
        }
      },
    });
  }, [sessionHistoryId, setSessionHistory, messageApi]);

  const loadHistoryResult = useCallback((item: CalculationResponse) => {
    setCalculatorState({
      ...calculatorState,
      currentDisplay: String(item.result),
      isResultDisplayed: true,
    });
    setHistoryDrawerVisible(false);
  }, [calculatorState, setCalculatorState]);

  const mainContainerStyle: CSSProperties = {
    display: 'flex',
    flexDirection: 'column',
    alignItems: 'center',
    justifyContent: 'center',
    minHeight: '100vh',
    width: '100%',
    padding: '16px',
    backgroundColor: '#f5f5f5',
  };

  const calculatorWrapperStyle: CSSProperties = {
    width: '100%',
    maxWidth: '400px',
    borderRadius: '16px',
    boxShadow: '0 8px 32px rgba(0,0,0,0.12)',
    overflow: 'hidden',
  };

  const headerRowStyle: CSSProperties = {
    display: 'flex',
    justifyContent: 'space-between',
    alignItems: 'center',
    padding: '8px 16px 0 16px',
  };

  const displaySectionStyle: CSSProperties = {
    padding: '16px',
    textAlign: 'right',
    minHeight: '120px',
    display: 'flex',
    flexDirection: 'column',
    justifyContent: 'flex-end',
  };

  const expressionDisplayStyle: CSSProperties = {
    fontSize: '16px',
    minHeight: '24px',
    color: '#999',
    textAlign: 'right',
    display: 'block',
  };

  const mainDisplayRowStyle: CSSProperties = {
    display: 'flex',
    alignItems: 'center',
    justifyContent: 'flex-end',
    gap: '8px',
  };

  const mainDisplayStyle: CSSProperties = {
    margin: '0',
    fontSize: 'clamp(24px, 8vw, 48px)',
    fontWeight: '300',
    textAlign: 'right',
    overflow: 'hidden',
    textOverflow: 'ellipsis',
    whiteSpace: 'nowrap',
    flex: '1',
    lineHeight: '1.2',
  };

  const memoryRowStyle: CSSProperties = {
    display: 'grid',
    gridTemplateColumns: 'repeat(4, 1fr)',
    gap: '4px',
    padding: '4px 16px',
  };

  const buttonGridStyle: CSSProperties = {
    display: 'grid',
    gridTemplateColumns: 'repeat(4, 1fr)',
    gap: '8px',
    padding: '8px 16px 16px 16px',
  };

  const numberButtonStyle: CSSProperties = {
    minWidth: '44px',
    minHeight: '56px',
    fontSize: '20px',
    fontWeight: '400',
    borderRadius: '12px',
    backgroundColor: '#f8f8f8',
    border: '1px solid #e8e8e8',
    transition: 'all 300ms ease',
  };

  const operatorButtonStyle: CSSProperties = {
    minWidth: '44px',
    minHeight: '56px',
    fontSize: '20px',
    fontWeight: '500',
    borderRadius: '12px',
    borderColor: '#1677ff',
    color: '#1677ff',
    transition: 'all 300ms ease',
  };

  const functionButtonStyle: CSSProperties = {
    minWidth: '44px',
    minHeight: '56px',
    fontSize: '16px',
    fontWeight: '500',
    borderRadius: '12px',
    backgroundColor: '#e0e0e0',
    border: 'none',
    transition: 'all 300ms ease',
  };

  const memoryButtonStyle: CSSProperties = {
    minWidth: '44px',
    minHeight: '44px',
    fontSize: '13px',
    fontWeight: '500',
    color: '#666',
  };

  const historyDrawerContentStyle: CSSProperties = {
    display: 'flex',
    flexDirection: 'column',
    height: '100%',
  };

  const historyListStyle: CSSProperties = {
    flex: '1',
    overflow: 'auto',
  };

  const historyItemStyle: CSSProperties = {
    cursor: 'pointer',
    padding: '12px 0',
    borderBottom: '1px solid #f0f0f0',
    transition: 'background-color 300ms ease',
  };

  return (
    <div style={mainContainerStyle}>
      {contextHolder}
      <Card bordered style={calculatorWrapperStyle}>
        <div style={headerRowStyle}>
          <Typography.Text strong style={{ fontSize: '16px', color: '#666' }}>
            Calculator
          </Typography.Text>
          <Button
            type="text"
            icon={<ClockCircleOutlined />}
            shape="circle"
            aria-label="Toggle history panel"
            style={{ minWidth: '44px', minHeight: '44px', fontSize: '18px' }}
            onClick={openHistoryDrawer}
          />
        </div>

        <div style={displaySectionStyle} role="region" aria-label="Calculator display">
          <Typography.Text type="secondary" style={expressionDisplayStyle} aria-label="Current expression">
            {displayExpression}
          </Typography.Text>
          <div style={mainDisplayRowStyle}>
            <Tooltip title="Copy result">
              <Button
                type="text"
                icon={<CopyOutlined />}
                size="small"
                aria-label="Copy result to clipboard"
                style={{ minWidth: '44px', minHeight: '44px' }}
                onClick={copyResult}
              />
            </Tooltip>
            <Typography.Title level={2} style={mainDisplayStyle} aria-live="polite" aria-label="Calculator result">
              {calculatorState.currentDisplay}
            </Typography.Title>
          </div>
        </div>

        {hasMemoryValue && (
          <div
            style={{
              width: '6px',
              height: '6px',
              borderRadius: '50%',
              backgroundColor: '#1677ff',
              marginLeft: '16px',
              marginBottom: '4px',
              visibility: 'visible',
            }}
            aria-label="Memory indicator"
          />
        )}

        <div style={memoryRowStyle} role="group" aria-label="Memory functions">
          <Button type="text" size="small" aria-label="Memory Clear" style={memoryButtonStyle} onClick={pressMemoryClear}>
            MC
          </Button>
          <Button type="text" size="small" aria-label="Memory Recall" style={memoryButtonStyle} onClick={pressMemoryRecall}>
            MR
          </Button>
          <Button type="text" size="small" aria-label="Memory Add" style={memoryButtonStyle} onClick={pressMemoryAdd}>
            M+
          </Button>
          <Button type="text" size="small" aria-label="Memory Subtract" style={memoryButtonStyle} onClick={pressMemorySubtract}>
            M-
          </Button>
        </div>

        <div style={buttonGridStyle} role="group" aria-label="Calculator buttons">
          <Button type="default" aria-label="All Clear" style={functionButtonStyle} onClick={pressAllClear}>
            AC
          </Button>
          <Button type="default" aria-label="Clear Entry" style={functionButtonStyle} onClick={pressClearEntry}>
            CE
          </Button>
          <Button type="default" aria-label="Backspace" style={functionButtonStyle} onClick={handleBackspace}>
            ⌫
          </Button>
          <Button type="primary" ghost aria-label="Divide" style={operatorButtonStyle} onClick={() => handleOperatorPress('/')}>
            ÷
          </Button>

          <Button type="default" aria-label="7" style={numberButtonStyle} onClick={() => handleDigitPress(7)}>
            7
          </Button>
          <Button type="default" aria-label="8" style={numberButtonStyle} onClick={() => handleDigitPress(8)}>
            8
          </Button>
          <Button type="default" aria-label="9" style={numberButtonStyle} onClick={() => handleDigitPress(9)}>
            9
          </Button>
          <Button type="primary" ghost aria-label="Multiply" style={operatorButtonStyle} onClick={() => handleOperatorPress('*')}>
            ×
          </Button>

          <Button type="default" aria-label="4" style={numberButtonStyle} onClick={() => handleDigitPress(4)}>
            4
          </Button>
          <Button type="default" aria-label="5" style={numberButtonStyle} onClick={() => handleDigitPress(5)}>
            5
          </Button>
          <Button type="default" aria-label="6" style={numberButtonStyle} onClick={() => handleDigitPress(6)}>
            6
          </Button>
          <Button type="primary" ghost aria-label="Subtract" style={operatorButtonStyle} onClick={() => handleOperatorPress('-')}>
            −
          </Button>

          <Button type="default" aria-label="1" style={numberButtonStyle} onClick={() => handleDigitPress(1)}>
            1
          </Button>
          <Button type="default" aria-label="2" style={numberButtonStyle} onClick={() => handleDigitPress(2)}>
            2
          </Button>
          <Button type="default" aria-label="3" style={numberButtonStyle} onClick={() => handleDigitPress(3)}>
            3
          </Button>
          <Button type="primary" ghost aria-label="Add" style={operatorButtonStyle} onClick={() => handleOperatorPress('+')}>
            +
          </Button>

          <Button type="default" aria-label="Toggle sign" style={numberButtonStyle} onClick={handleToggleSign}>
            +/−
          </Button>
          <Button type="default" aria-label="0" style={numberButtonStyle} onClick={() => handleDigitPress(0)}>
            0
          </Button>
          <Button type="default" aria-label="Decimal point" style={numberButtonStyle} onClick={handleDecimalPress}>
            .
          </Button>
          <Button type="default" aria-label="Percentage" style={functionButtonStyle} onClick={handlePercentage}>
            %
          </Button>
          <Button
            type="primary"
            aria-label="Equals"
            style={{
              minWidth: '44px',
              minHeight: '56px',
              fontSize: '24px',
              fontWeight: '500',
              borderRadius: '12px',
              backgroundColor: '#1677ff',
              color: '#ffffff',
              border: 'none',
              transition: 'all 300ms ease',
              gridColumn: 'span 1',
            }}
            onClick={pressEquals}
          >
            =
          </Button>
        </div>
      </Card>

      <Drawer
        title="Calculation History"
        placement="right"
        width={360}
        closable
        onClose={closeHistoryDrawer}
        open={historyDrawerVisible}
      >
        <div style={historyDrawerContentStyle}>
          <List
            dataSource={formattedHistory}
            locale={{ emptyText: 'No calculations yet' }}
            size="small"
            style={historyListStyle}
            renderItem={(item: CalculationResponse) => (
              <List.Item style={historyItemStyle} onClick={() => loadHistoryResult(item)}>
                <div>
                  <Typography.Text strong style={{ fontSize: '14px', display: 'block' }}>
                    {item.expression} = {item.result}
                  </Typography.Text>
                  <Typography.Text type="secondary" style={{ fontSize: '12px', display: 'block' }}>
                    {new Date(item.timestamp).toLocaleString()}
                  </Typography.Text>
                </div>
              </List.Item>
            )}
          />
          <Button
            type="default"
            danger
            block
            icon={<DeleteOutlined />}
            aria-label="Clear all history"
            style={{ marginTop: '16px', minHeight: '44px' }}
            onClick={clearSessionHistory}
          >
            Clear History
          </Button>
        </div>
      </Drawer>
    </div>
  );
};

export default CalculatorPage;