import React, { useState, useCallback, useEffect } from 'react';
import { Tabs, Tab, Box, Button, Paper, Typography, LinearProgress } from '@mui/material';
import { Job, Candidate, SkillAssessment } from 'types/types';
import { Scrollable } from './Scrollable';
import { useAuth } from 'hooks/AuthContext';
import * as Types from 'types/types';
import { StyledMarkdown } from './StyledMarkdown';
import InputIcon from '@mui/icons-material/Input';
import TuneIcon from '@mui/icons-material/Tune';
import ArticleIcon from '@mui/icons-material/Article';
import { StatusBox, StatusIcon } from './ui/StatusIcon';
import { CopyBubble } from './CopyBubble';
import { useAppState } from 'hooks/GlobalContext';
import { StreamingOptions } from 'services/api-client';
import { useNavigate } from 'react-router-dom';

interface ResumeGeneratorProps {
  job: Job;
  candidate: Candidate;
  skills: SkillAssessment[];
  onComplete?: (resume: string) => void;
}

const ResumeGenerator: React.FC<ResumeGeneratorProps> = (props: ResumeGeneratorProps) => {
  const { job, candidate, skills, onComplete } = props;
  const { setSnack } = useAppState();
  const navigate = useNavigate();
  const { apiClient, user } = useAuth();
  const [resume, setResume] = useState<string>('');
  const [prompt, setPrompt] = useState<string>('');
  const [systemPrompt, setSystemPrompt] = useState<string>('');
  const [generated, setGenerated] = useState<boolean>(false);
  const [tabValue, setTabValue] = useState<string>('resume');
  const [status, setStatus] = useState<string>('');
  const [statusType, setStatusType] = useState<Types.ApiActivityType | null>(null);
  const [error, setError] = useState<Types.ChatMessageError | null>(null);

  const handleTabChange = (event: React.SyntheticEvent, newValue: string): void => {
    setTabValue(newValue);
  };

  useEffect(() => {
    if (!job || !candidate || !skills || generated) {
      return;
    }

    setGenerated(true);

    setStatusType('thinking');
    setStatus('Starting resume generation...');

    const generateResumeHandlers: StreamingOptions<Types.ChatMessageResume> = {
      onMessage: (message: Types.ChatMessageResume) => {
        const resume: Types.Resume = message.resume;
        setSystemPrompt(resume.systemPrompt || '');
        setPrompt(resume.prompt || '');
        setResume(resume.resume || '');
        setStatus('');
      },
      onStreaming: (chunk: Types.ChatMessageStreaming) => {
        if (status === '') {
          setStatus('Generating resume...');
          setStatusType('generating');
        }
        setResume(chunk.content);
      },
      onStatus: (status: Types.ChatMessageStatus) => {
        console.log('status:', status.content);
        setStatusType(status.activity);
        setStatus(status.content);
      },
      onComplete: () => {
        onComplete && onComplete(resume);
      },
      onError: (error: Types.ChatMessageError) => {
        console.log('error:', error);
        setStatusType(null);
        setStatus(error.content);
        setError(error);
      },
    };

    const generateResume = async (): Promise<void> => {
      const request = await apiClient.generateResume(
        candidate.id || '',
        job.id || '',
        generateResumeHandlers
      );
      await request.promise;
    };

    generateResume();
  }, [
    job,
    candidate,
    apiClient,
    resume,
    skills,
    generated,
    status,
    setSystemPrompt,
    setPrompt,
    setResume,
    onComplete,
    setStatus,
    setStatusType,
    setError,
  ]);

  const handleSave = useCallback(async () => {
    if (!resume) {
      setSnack('No resume to save!');
      return;
    }

    try {
      if (!candidate.id || !job.id) {
        setSnack('Candidate or job ID is missing.');
        return;
      }
      const submission: Types.Resume = {
        jobId: job.id,
        candidateId: candidate.id,
        resume,
        systemPrompt,
        prompt,
      };
      const controller = apiClient.saveResume(submission);
      const result = await controller.promise;
      if (result.resume.id) {
        setSnack('Resume saved successfully!');
        navigate(`/candidate/resumes/${result.resume.id}`);
      }
    } catch (error) {
      console.error('Error saving resume:', error);
      setSnack('Error saving resume.');
    }
  }, [apiClient, candidate.id, job.id, resume, setSnack, navigate, prompt, systemPrompt]);

  return (
    <Box
      className="ResumeGenerator"
      sx={{
        display: 'flex',
        flexDirection: 'column',
      }}
    >
      {user?.isAdmin && (
        <Box sx={{ borderBottom: 1, borderColor: 'divider', mb: 1 }}>
          <Tabs value={tabValue} onChange={handleTabChange} centered>
            <Tab disabled={systemPrompt === ''} value="system" icon={<TuneIcon />} label="System" />
            <Tab disabled={prompt === ''} value="prompt" icon={<InputIcon />} label="Prompt" />
            <Tab disabled={resume === ''} value="resume" icon={<ArticleIcon />} label="Resume" />
          </Tabs>
        </Box>
      )}

      {status && (
        <Box sx={{ mt: 0, mb: 1 }}>
          <StatusBox>
            {statusType && <StatusIcon type={statusType} />}
            <Typography variant="body2" sx={{ ml: 1 }}>
              {status || 'Processing...'}
            </Typography>
          </StatusBox>
          {status && !error && <LinearProgress sx={{ mt: 1 }} />}
        </Box>
      )}

      <Paper elevation={3} sx={{ p: 3, m: 1, mt: 0 }}>
        <Scrollable autoscroll sx={{ display: 'flex', flexGrow: 1, position: 'relative' }}>
          {tabValue === 'system' && <pre>{systemPrompt}</pre>}
          {tabValue === 'prompt' && <pre>{prompt}</pre>}
          {tabValue === 'resume' && (
            <>
              <CopyBubble
                onClick={(): void => {
                  setSnack('Resume copied to clipboard!');
                }}
                sx={{ position: 'absolute', top: 0, right: 0 }}
                content={resume}
              />
              <StyledMarkdown content={resume} />
            </>
          )}
        </Scrollable>
      </Paper>

      {resume && !status && !error && (
        <Button onClick={handleSave} variant="contained" color="primary" sx={{ mt: 2 }}>
          Save Resume and Edit
        </Button>
      )}
    </Box>
  );
};

export { ResumeGenerator };
