import React, { useState, useEffect, useCallback, JSX, useMemo } from 'react';
import {
  Box,
  Typography,
  Accordion,
  AccordionSummary,
  AccordionDetails,
  CircularProgress,
  Chip,
  Card,
  CardContent,
  useTheme,
  LinearProgress,
  useMediaQuery,
  Button,
  Paper,
  SxProps,
  Tooltip,
  IconButton,
} from '@mui/material';
import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
import CheckCircleIcon from '@mui/icons-material/CheckCircle';
import ErrorIcon from '@mui/icons-material/Error';
import ModelTrainingIcon from '@mui/icons-material/ModelTraining';
import PendingIcon from '@mui/icons-material/Pending';
import WarningIcon from '@mui/icons-material/Warning';
import { Candidate, SkillAssessment, SkillStatus } from 'types/types';
import { useAuth } from 'hooks/AuthContext';
import { BackstoryPageProps } from './BackstoryTab';
import { Job } from 'types/types';
import * as Types from 'types/types';
import { JobInfo } from './ui/JobInfo';
import { Scrollable } from 'components/Scrollable';

interface JobAnalysisScore {
  score: number;
  skills: SkillAssessment[];
}

interface JobAnalysisProps extends BackstoryPageProps {
  job: Job;
  candidate: Candidate;
  variant?: 'small' | 'normal';
  onAnalysisComplete: (analysis: JobAnalysisScore) => void;
}

interface SkillMatch extends SkillAssessment {
  domain: string;
  status: SkillStatus;
  matchScore: number;
}

const JobMatchScore: React.FC<{ score: number; variant?: 'small' | 'normal'; sx?: SxProps }> = ({
  variant = 'normal',
  score,
  sx = {},
}) => {
  const theme = useTheme();
  const getMatchColor = (score: number): string => {
    if (score >= 80) return theme.palette.success.main;
    if (score >= 60) return theme.palette.info.main;
    if (score >= 40) return theme.palette.warning.main;
    return theme.palette.error.main;
  };
  const suffix = variant === 'small' ? '' : ' Match';

  return (
    <Box
      className="JobMatchScore"
      sx={{
        justifyContent: 'center',
        m: 0,
        p: 0,
        width: variant === 'small' ? '8rem' : '10rem',
        display: 'flex',
        alignItems: 'center',
        flexDirection: 'row',
        ...sx,
      }}
    >
      <Chip
        label={
          score >= 80
            ? `Excellent${suffix}`
            : score >= 60
            ? `Good${suffix}`
            : score >= 40
            ? `Partial${suffix}`
            : `Low${suffix}`
        }
        sx={{
          bgcolor: getMatchColor(score),
          color: 'white',
          fontWeight: 'bold',
          fontSize: variant === 'small' ? '0.7rem' : '1rem',
        }}
      />
      {variant !== 'small' && (
        <Box
          sx={{
            position: 'relative',
            display: 'inline-flex',
            p: 0,
            m: 0,
          }}
        >
          <CircularProgress
            variant="determinate"
            value={score}
            size={60}
            thickness={5}
            sx={{
              color: getMatchColor(score),
            }}
          />
          <Box
            sx={{
              top: 0,
              left: 0,
              bottom: 0,
              right: 0,
              position: 'absolute',
              display: 'flex',
              alignItems: 'center',
              justifyContent: 'center',
            }}
          >
            <Typography
              variant="caption"
              component="div"
              sx={{ fontWeight: 'bold', fontSize: '1rem' }}
            >
              {`${Math.round(score)}%`}
            </Typography>
          </Box>
        </Box>
      )}
    </Box>
  );
};

const calculateScore = (skillMatch: SkillAssessment): number => {
  let score = 0;
  switch (skillMatch.evidenceStrength.toUpperCase()) {
    case 'STRONG':
      score = 100;
      break;
    case 'MODERATE':
      score = 75;
      break;
    case 'WEAK':
      score = 50;
      break;
    case 'NONE':
      score = 0;
      break;
  }
  if (
    skillMatch.evidenceStrength === 'none' &&
    skillMatch.evidenceDetails &&
    skillMatch.evidenceDetails.length > 3
  ) {
    score = Math.min(skillMatch.evidenceDetails.length * 8, 40);
  }
  return score;
};

const JobMatchAnalysis: React.FC<JobAnalysisProps> = (props: JobAnalysisProps) => {
  const { job, candidate, onAnalysisComplete, variant = 'normal' } = props;
  const { apiClient } = useAuth();
  const theme = useTheme();
  const [requirements, setRequirements] = useState<{ requirement: string; domain: string }[]>([]);
  const [skillMatches, setSkillMatches] = useState<SkillMatch[]>([]);
  const [loadingRequirements, setLoadingRequirements] = useState<boolean>(false);
  const [expanded, setExpanded] = useState<string | false>(false);
  const [overallScore, setOverallScore] = useState<number>(0);
  const [analyzing, setAnalyzing] = useState<boolean>(false);
  const [matchStatus, setMatchStatus] = useState<string>('');
  const [percentage, setPercentage] = useState<number>(0);
  const [analysis, setAnalysis] = useState<JobAnalysisScore | null>(null);
  const [startAnalysis, setStartAnalysis] = useState<boolean>(true);
  const [firstRun, setFirstRun] = useState<boolean>(true);
  const isMobile = useMediaQuery(theme.breakpoints.down('sm'));

  // Handle accordion expansion
  const handleAccordionChange =
    (panel: string) => (event: React.SyntheticEvent, isExpanded: boolean) => {
      setExpanded(isExpanded ? panel : false);
    };

  const initializeRequirements = useCallback(
    (job: Job): void => {
      if (!job || !job.requirements) {
        return;
      }
      const requirements: { requirement: string; domain: string }[] = [];
      if (job.requirements?.technicalSkills) {
        job.requirements.technicalSkills.required?.forEach(req =>
          requirements.push({
            requirement: req,
            domain: 'Technical Skills (required)',
          })
        );
        job.requirements.technicalSkills.preferred?.forEach(req =>
          requirements.push({
            requirement: req,
            domain: 'Technical Skills (preferred)',
          })
        );
      }
      if (job.requirements?.experienceRequirements) {
        job.requirements.experienceRequirements.required?.forEach(req =>
          requirements.push({ requirement: req, domain: 'Experience (required)' })
        );
        job.requirements.experienceRequirements.preferred?.forEach(req =>
          requirements.push({
            requirement: req,
            domain: 'Experience (preferred)',
          })
        );
      }
      if (job.requirements?.softSkills) {
        job.requirements.softSkills.forEach(req =>
          requirements.push({ requirement: req, domain: 'Soft Skills' })
        );
      }
      if (job.requirements?.experience) {
        job.requirements.experience.forEach(req =>
          requirements.push({ requirement: req, domain: 'Experience' })
        );
      }
      if (job.requirements?.education) {
        job.requirements.education.forEach(req =>
          requirements.push({ requirement: req, domain: 'Education' })
        );
      }
      if (job.requirements?.certifications) {
        job.requirements.certifications.forEach(req =>
          requirements.push({ requirement: req, domain: 'Certifications' })
        );
      }
      if (job.requirements?.preferredAttributes) {
        job.requirements.preferredAttributes.forEach(req =>
          requirements.push({ requirement: req, domain: 'Preferred Attributes' })
        );
      }

      const initialSkillMatches: SkillMatch[] = requirements.map(req => ({
        skill: req.requirement,
        skillModified: req.requirement,
        candidateId: candidate.id || '',
        domain: req.domain,
        status: 'waiting' as const,
        assessment: '',
        description: '',
        evidenceFound: false,
        evidenceStrength: 'none',
        evidenceDetails: [],
        matchScore: 0,
      }));

      setRequirements(requirements);
      setSkillMatches(initialSkillMatches);
      setLoadingRequirements(false);
      setOverallScore(0);
    },
    [candidate.id]
  );

  useEffect(() => {
    initializeRequirements(job);
  }, [job, initializeRequirements]);

  const skillMatchHandlers = useMemo(() => {
    return {
      onStatus: (status: Types.ChatMessageStatus): void => {
        console.log('Skill Match Status:', status.content);
        setMatchStatus(status.content);
      },
    };
  }, [setMatchStatus]);

  // Fetch match data for each requirement
  useEffect(() => {
    if (
      (!startAnalysis && !firstRun) ||
      analyzing ||
      !job.requirements ||
      requirements.length === 0
    ) {
      return;
    }

    const fetchMatchData = async (firstRun: boolean): Promise<void> => {
      const currentAnalysis = await apiClient.getJobAnalysis(job, candidate);
      for (let i = 0; i < requirements.length; i++) {
        try {
          let match: SkillMatch;
          const existingMatch = currentAnalysis?.skills.find(
            (match: SkillAssessment) => match.skill === requirements[i].requirement
          );
          if (existingMatch) {
            match = {
              ...existingMatch,
              status: 'complete',
              matchScore: calculateScore(existingMatch),
              domain: requirements[i].domain,
            };
          } else {
            if (firstRun) {
              continue;
            }
            setSkillMatches(prev => {
              const updated = [...prev];
              updated[i] = { ...updated[i], status: 'pending' };
              return updated;
            });

            const request = await apiClient.candidateMatchForRequirement(
              candidate.id || '',
              requirements[i].requirement,
              false,
              skillMatchHandlers
            );
            const result = await request.promise; /* Wait for the streaming result to complete */
            const skillMatch = result.skillAssessment;
            setMatchStatus('');

            match = {
              ...skillMatch,
              status: 'complete',
              matchScore: calculateScore(skillMatch),
              domain: requirements[i].domain,
            };
          }

          setSkillMatches(prev => {
            const updated = [...prev];
            updated[i] = match;
            return updated;
          });

          // Update overall score
          setSkillMatches(current => {
            const completedMatches = current.filter(match => match.status === 'complete');
            if (completedMatches.length > 0) {
              const newOverallScore =
                completedMatches.reduce((sum, match) => sum + match.matchScore, 0) /
                completedMatches.length;
              setOverallScore(Math.round(newOverallScore));
            }
            return current;
          });
        } catch (error) {
          console.error(`Error fetching match for requirement ${requirements[i]}:`, error);
          setSkillMatches(prev => {
            const updated = [...prev];
            updated[i] = {
              ...updated[i],
              status: 'error',
              assessment: 'Failed to analyze this requirement.',
            };
            return updated;
          });
        }
        setPercentage(Math.round(((i + 1) / requirements.length) * 100));
      }
    };

    setAnalyzing(true);
    setPercentage(0);

    fetchMatchData(firstRun).then(() => {
      setAnalyzing(false);
      setStartAnalysis(false);
    });
    setFirstRun(false);
  }, [
    job,
    startAnalysis,
    analyzing,
    requirements,
    loadingRequirements,
    apiClient,
    candidate.id,
    skillMatchHandlers,
    firstRun,
  ]);

  useEffect(() => {
    if (skillMatches.length === 0) {
      return;
    }
    const finishedAnalysis = skillMatches.every(
      match => match.status === 'complete' || match.status === 'error'
    );
    if (!finishedAnalysis) {
      return;
    }
    if (analysis && analysis.score === overallScore) {
      return; // No change in score, skip setting analysis
    }
    const newAnalysis: JobAnalysisScore = {
      score: overallScore,
      skills: skillMatches,
    };
    setAnalysis(newAnalysis);
    onAnalysisComplete && onAnalysisComplete(newAnalysis);
  }, [onAnalysisComplete, skillMatches, overallScore, analysis]);

  // Get color based on match score
  const getMatchColor = (score: number): string => {
    if (score >= 80) return theme.palette.success.main;
    if (score >= 60) return theme.palette.info.main;
    if (score >= 40) return theme.palette.warning.main;
    return theme.palette.error.main;
  };

  // Get icon based on status
  const getStatusIcon = (status: string, score: number): JSX.Element => {
    if (status === 'pending' || status === 'waiting') return <PendingIcon />;
    if (status === 'error') return <ErrorIcon color="error" />;
    if (score >= 70) return <CheckCircleIcon color="success" />;
    if (score >= 40) return <WarningIcon color="warning" />;
    return <ErrorIcon color="error" />;
  };

  const handleAssesmentRegenerate = async (index: number, skill: string): Promise<void> => {
    setSkillMatches(prev => {
      const updated = [...prev];
      updated[index] = {
        ...updated[index],
        status: 'pending',
        assessment: '',
        evidenceDetails: [],
        evidenceStrength: 'none',
        matchScore: 0,
      };
      return updated;
    });
    setMatchStatus('Regenerating assessment...');
    const request = apiClient.candidateMatchForRequirement(
      candidate.id || '',
      skill,
      true,
      skillMatchHandlers
    );
    const result = await request.promise; /* Wait for the streaming result to complete */
    const skillMatch = result.skillAssessment;
    setMatchStatus('');
    setSkillMatches(prev => {
      const updated = [...prev];
      updated[index] = {
        ...skillMatch,
        status: 'complete',
        matchScore: calculateScore(skillMatch),
        domain: updated[index].domain,
      };
      return updated;
    });
    // Update overall score
    setSkillMatches(current => {
      const completedMatches = current.filter(match => match.status === 'complete');
      if (completedMatches.length > 0) {
        const newOverallScore =
          completedMatches.reduce((sum, match) => sum + match.matchScore, 0) /
          completedMatches.length;
        setOverallScore(Math.round(newOverallScore));
      }
      return current;
    });
    setAnalysis({
      score: overallScore,
      skills: skillMatches,
    });
    onAnalysisComplete &&
      onAnalysisComplete({
        score: overallScore,
        skills: skillMatches,
      });
    setStartAnalysis(false);
    setAnalyzing(false);
    setFirstRun(false);
  };

  const beginAnalysis = (): void => {
    initializeRequirements(job);
    setStartAnalysis(true);
  };

  return (
    <Scrollable
      className="JobMatchAnalysis"
      sx={{
        display: 'flex',
        flexDirection: 'column',
        m: 0,
        p: 1,
        width: '100%',
        minHeight: 0,
        flexGrow: 1,
      }}
    >
      {variant !== 'small' && <JobInfo job={job} variant="normal" />}

      <Box
        sx={{
          display: 'flex',
          flexDirection: 'row',
          alignItems: 'center',
          mb: isMobile ? 1 : 2,
          gap: 1,
          justifyContent: 'space-between',
        }}
      >
        <Box
          sx={{
            display: 'flex',
            flexDirection: isMobile ? 'column' : 'row',
            flexGrow: 1,
            gap: 1,
          }}
        >
          {analyzing && overallScore !== 0 && (
            <JobMatchScore
              score={overallScore}
              sx={{ width: isMobile ? '100%' : 'auto', flexGrow: 1 }}
            />
          )}
          {analyzing && (
            <Paper
              sx={{
                width: '10rem',
                ml: 1,
                p: 1,
                gap: 1,
                display: 'flex',
                justifyContent: 'space-between',
                alignItems: 'center',
                flexDirection: 'column',
              }}
            >
              <Typography variant="h5" component="h2" sx={{ m: 0, fontSize: '1rem' }}>
                Analyzing
              </Typography>
              <Box
                sx={{
                  position: 'relative',
                  display: 'inline-flex',
                }}
              >
                <CircularProgress
                  variant="determinate"
                  value={percentage}
                  size={60}
                  thickness={5}
                  sx={{
                    color: 'orange',
                  }}
                />
                <Box
                  sx={{
                    top: 0,
                    left: 0,
                    bottom: 0,
                    right: 0,
                    position: 'absolute',
                    display: 'flex',
                    alignItems: 'center',
                    justifyContent: 'center',
                  }}
                >
                  <Typography variant="caption" component="div" sx={{ fontWeight: 'bold' }}>
                    {`${Math.round(percentage)}%`}
                  </Typography>
                </Box>
              </Box>
            </Paper>
          )}
        </Box>
        <Button
          sx={{ marginLeft: 'auto' }}
          disabled={analyzing || startAnalysis}
          onClick={beginAnalysis}
          variant="contained"
        >
          {analyzing ? 'Assessment in Progress' : 'Analyze Waiting Skills'}
        </Button>
      </Box>

      {loadingRequirements ? (
        <Box sx={{ display: 'flex', justifyContent: 'center', p: 4 }}>
          <CircularProgress />
          <Typography variant="h6" sx={{ ml: 2 }}>
            Analyzing job requirements...
          </Typography>
        </Box>
      ) : (
        <Box>
          <Typography variant="h5" component="h2" gutterBottom>
            Requirements Analysis
          </Typography>

          {skillMatches.map((match, index) => (
            <Accordion
              key={index}
              expanded={expanded === `panel${index}`}
              onChange={handleAccordionChange(`panel${index}`)}
              sx={{
                mb: 2,
                border: '1px solid',
                borderColor:
                  match.status === 'complete'
                    ? getMatchColor(match.matchScore)
                    : theme.palette.divider,
              }}
            >
              <AccordionSummary
                expandIcon={<ExpandMoreIcon />}
                aria-controls={`panel${index}bh-content`}
                id={`panel${index}bh-header`}
                sx={{
                  bgcolor:
                    match.status === 'complete'
                      ? `${getMatchColor(match.matchScore)}22` // Add transparency
                      : 'inherit',
                }}
              >
                <Box
                  sx={{
                    display: 'flex',
                    alignItems: 'center',
                    width: '100%',
                    justifyContent: 'space-between',
                  }}
                >
                  <Box sx={{ display: 'flex', alignItems: 'center' }}>
                    {getStatusIcon(match.status, match.matchScore)}
                    <Box
                      sx={{
                        display: 'flex',
                        flexDirection: 'column',
                        gap: 0,
                        p: 0,
                        m: 0,
                      }}
                    >
                      <Typography
                        sx={{
                          ml: 1,
                          mb: 0,
                          fontWeight: 'medium',
                          marginBottom: '0px !important',
                        }}
                      >
                        {match.skill}
                      </Typography>
                      <Typography variant="caption" sx={{ ml: 1, fontWeight: 'light' }}>
                        {match.domain}
                      </Typography>
                    </Box>
                  </Box>

                  {match.status === 'complete' ? (
                    <Chip
                      label={`${match.matchScore}% Match`}
                      size="small"
                      sx={{
                        bgcolor: getMatchColor(match.matchScore),
                        color: 'white',
                        minWidth: 90,
                        pointerEvents: 'none',
                      }}
                    />
                  ) : match.status === 'waiting' ? (
                    <Chip
                      label="Waiting..."
                      size="small"
                      sx={{
                        bgcolor: 'rgb(189, 173, 85)',
                        color: 'white',
                        minWidth: 90,
                        pointerEvents: 'none',
                      }}
                    />
                  ) : match.status === 'pending' ? (
                    <Chip
                      label="Analyzing..."
                      size="small"
                      sx={{
                        bgcolor: theme.palette.grey[400],
                        color: 'white',
                        minWidth: 90,
                        pointerEvents: 'none',
                      }}
                    />
                  ) : (
                    <Chip
                      label="Error"
                      size="small"
                      sx={{
                        bgcolor: theme.palette.error.main,
                        color: 'white',
                        minWidth: 90,
                        pointerEvents: 'none',
                      }}
                    />
                  )}
                </Box>
              </AccordionSummary>

              <AccordionDetails>
                {match.status === 'pending' ? (
                  <Box sx={{ width: '100%', p: 2 }}>
                    <LinearProgress />
                    <Typography sx={{ mt: 2 }}>
                      Analyzing candidate&apos;s match for this requirement... {matchStatus}
                    </Typography>
                  </Box>
                ) : match.status === 'error' ? (
                  <Typography color="error">
                    {match.assessment || 'An error occurred while analyzing this requirement.'}
                  </Typography>
                ) : (
                  <Box>
                    <Typography variant="h6" gutterBottom>
                      Assessment
                    </Typography>

                    <Typography paragraph sx={{ mb: 3 }}>
                      {match.assessment}
                    </Typography>

                    <Typography variant="h6" gutterBottom>
                      Supporting Evidence
                    </Typography>
                    {match.evidenceDetails && match.evidenceDetails.length > 0 ? (
                      match.evidenceDetails.map((evidence, evndex) => (
                        <Card
                          key={evndex}
                          variant="outlined"
                          sx={{
                            mb: 2,
                            borderLeft: '4px solid',
                            borderColor: theme.palette.primary.main,
                          }}
                        >
                          <CardContent>
                            <Typography
                              variant="body1"
                              component="div"
                              sx={{ mb: 1, fontStyle: 'italic' }}
                            >
                              &quot;{evidence.quote}&quot;
                            </Typography>
                            <Box
                              sx={{
                                display: 'flex',
                                justifyContent: 'space-between',
                                alignItems: 'flex-start',
                                flexDirection: 'column',
                              }}
                            >
                              <Typography variant="body2" color="text.secondary">
                                Relevance: {evidence.context}
                              </Typography>
                              <Typography variant="caption" color="text.secondary">
                                Source: {evidence.source}
                              </Typography>
                              {/* <Chip
                                size="small"
                                label={`Relevance: ${citation.relevance}%`}
                                sx={{
                                  bgcolor: theme.palette.grey[200],
                                }}
                              /> */}
                            </Box>
                          </CardContent>
                        </Card>
                      ))
                    ) : (
                      <Typography color="text.secondary">
                        No specific evidence found in candidate&apos;s profile.
                      </Typography>
                    )}
                    <Typography variant="h6" gutterBottom>
                      Skill description
                    </Typography>
                    <Typography paragraph>{match.description}</Typography>
                    {match.status === 'complete' && (
                      <Tooltip title="Regenerate Assessment">
                        <IconButton
                          size="small"
                          onClick={(e): void => {
                            e.stopPropagation();
                            handleAssesmentRegenerate(index, match.skill);
                          }}
                        >
                          <ModelTrainingIcon />
                        </IconButton>
                      </Tooltip>
                    )}
                    {/* { match.ragResults && match.ragResults.length !== 0 && <>
                          <Typography variant="h6" gutterBottom>
                            RAG Information
                          </Typography>
                          <VectorVisualizer inline rag={match.ragResults[0]} />
                        </>
                        } */}
                  </Box>
                )}
              </AccordionDetails>
            </Accordion>
          ))}
        </Box>
      )}
    </Scrollable>
  );
};

export type { JobAnalysisScore };
export { JobMatchAnalysis, JobMatchScore };
