import { useState } from 'preact/hooks';
import { MindforgeApiService } from '../services/MindforgeApiService';
import { FileTreeComponent } from './FileTreeComponent';
import { Button } from './Button';
import * as diff from 'diff';
import { marked } from 'marked';
import './VerificadorComponent.css';

function utf8ToBase64(str: string): string {
  const bytes = new TextEncoder().encode(str);
  const binary = Array.from(bytes, byte => String.fromCharCode(byte)).join('');
  return window.btoa(binary);
}

type CheckTypeEnum = 'language' | 'content' | 'both';

interface FileResult {
  path: string;
  fileName: string;
  originalContent: string;
  languageResult: string | null;
  contentResult: string | null;
  error: string | null;
}

export function VerificadorComponent() {
  const [selectedPaths, setSelectedPaths] = useState<string[]>([]);
  const [checkType, setCheckType] = useState<CheckTypeEnum>('language');
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const [results, setResults] = useState<FileResult[]>([]);

  const handleSubmit = async () => {
    if (selectedPaths.length === 0) {
      setError('Selecione pelo menos um arquivo do repositório.');
      return;
    }

    setLoading(true);
    setError(null);
    setResults([]);

    try {
      const fileResults = await Promise.all(
        selectedPaths.map(async (path): Promise<FileResult> => {
          const fileName = path.split('/').pop() ?? path;
          try {
            const { content } = await MindforgeApiService.getFileContent(path);
            const base64Content = utf8ToBase64(content);

            let languageResult: string | null = null;
            let contentResult: string | null = null;

            if (checkType === 'both') {
              const [langRes, contRes] = await Promise.all([
                MindforgeApiService.checkFile({ fileContent: base64Content, fileName, checkType: 'language' }),
                MindforgeApiService.checkFile({ fileContent: base64Content, fileName, checkType: 'content' }),
              ]);
              languageResult = langRes.result;
              contentResult = contRes.result;
            } else {
              const res = await MindforgeApiService.checkFile({ fileContent: base64Content, fileName, checkType });
              if (checkType === 'language') languageResult = res.result;
              else contentResult = res.result;
            }

            return { path, fileName, originalContent: content, languageResult, contentResult, error: null };
          } catch (err: any) {
            return { path, fileName, originalContent: '', languageResult: null, contentResult: null, error: err.message };
          }
        })
      );

      setResults(fileResults);
    } catch (err: any) {
      setError(err.message || 'Ocorreu um erro ao processar os arquivos.');
    } finally {
      setLoading(false);
    }
  };

  const renderDiff = (original: string, updated: string) => {
    const diffResult = diff.diffWordsWithSpace(original, updated);
    return (
      <div className="diff-view">
        {diffResult.map((part, index) => {
          const className = part.added ? 'diff-added' : part.removed ? 'diff-removed' : '';
          return (
            <span key={index} className={className}>
              {part.value}
            </span>
          );
        })}
      </div>
    );
  };

  return (
    <div className="verificador-container">
      <h2 className="verificador-title">Verificador de Arquivos</h2>
      <p className="verificador-subtitle">Selecione os arquivos do repositório para validação de linguagem ou conteúdo.</p>

      <div className="verificador-form">
        <div className="input-group">
          <label>Arquivos do Repositório</label>
          <FileTreeComponent selectedPaths={selectedPaths} onSelectionChange={setSelectedPaths} />
          {selectedPaths.length > 0 && (
            <div class="select-status">
              {selectedPaths.length === 1 ? '1 arquivo selecionado' : `${selectedPaths.length} arquivos selecionados`}
            </div>
          )}
        </div>

        <div className="input-group">
          <label>Tipo de Verificação</label>
          <select
            className="select-input"
            value={checkType}
            onChange={(e) => setCheckType((e.target as HTMLSelectElement).value as CheckTypeEnum)}
          >
            <option value="language">Linguagem</option>
            <option value="content">Conteúdo</option>
            <option value="both">Linguagem e Conteúdo</option>
          </select>
        </div>

        <Button variant="primary" onClick={handleSubmit} disabled={loading} style={{ marginTop: '0.5rem' }}>
          {loading ? 'Processando...' : 'Verificar'}
        </Button>

        {error && <div class="verificador-error">{error}</div>}
      </div>

      {loading && (
        <div class="loading-indicator">
          <span class="loading-dot"></span>
          <span>Analisando sua forja mental...</span>
        </div>
      )}

      {!loading && results.length > 0 && (
        <div className="response-section">
          {results.map((fileResult) => (
            <div key={fileResult.path} className="file-result-block">
              <div className="file-result-title">{fileResult.fileName}</div>

              {fileResult.error && (
                <div class="verificador-error">{fileResult.error}</div>
              )}

              {!fileResult.error && checkType === 'language' && fileResult.languageResult && (
                <div className="side-pane">
                  <div className="pane-title">Linguagem (Diff)</div>
                  <div className="response-content">
                    {renderDiff(fileResult.originalContent, fileResult.languageResult)}
                  </div>
                </div>
              )}

              {!fileResult.error && checkType === 'content' && fileResult.contentResult && (
                <div className="side-pane">
                  <div className="pane-title">Conteúdo</div>
                  <div
                    className="response-content markdown-body"
                    dangerouslySetInnerHTML={{ __html: marked.parse(fileResult.contentResult) as string }}
                  />
                </div>
              )}

              {!fileResult.error && checkType === 'both' && fileResult.languageResult && fileResult.contentResult && (
                <div className="side-by-side">
                  <div className="side-pane">
                    <div className="pane-title">Linguagem (Diff)</div>
                    <div className="response-content" style={{ minHeight: '200px' }}>
                      {renderDiff(fileResult.originalContent, fileResult.languageResult)}
                    </div>
                  </div>
                  <div className="side-pane">
                    <div className="pane-title">Conteúdo</div>
                    <div
                      className="response-content markdown-body"
                      style={{ minHeight: '200px' }}
                      dangerouslySetInnerHTML={{ __html: marked.parse(fileResult.contentResult) as string }}
                    />
                  </div>
                </div>
              )}
            </div>
          ))}
        </div>
      )}
    </div>
  );
}
