import React, { useState, useEffect, useRef } from 'react';
import JSZip from 'jszip';
import CopyIcon from './icons/CopyIcon';
import DownloadIcon from './icons/DownloadIcon';
import { AppStatus, AppType } from '../types';

interface CodeDisplayProps {
  appType: AppType;
  pythonCode?: string;
  cppFiles?: Record<string, string> | null;
  status: AppStatus;
}

const PythonCodeView: React.FC<{ code: string }> = ({ code }) => {
  const [copyText, setCopyText] = useState('Copy Code');
  const codeRef = useRef<HTMLElement>(null);
  const finalCode = code.replace(/\n```$/, '').trim();

  useEffect(() => {
    // @ts-ignore
    if (window.hljs && codeRef.current) {
        // @ts-ignore
        window.hljs.highlightElement(codeRef.current);
    }
  }, [finalCode]);

  const handleCopy = () => {
    navigator.clipboard.writeText(finalCode).then(() => {
      setCopyText('Copied!');
      setTimeout(() => setCopyText('Copy Code'), 2000);
    });
  };

  const handleDownload = () => {
    const blob = new Blob([finalCode], { type: 'text/python' });
    const url = URL.createObjectURL(blob);
    const a = document.createElement('a');
    a.href = url;
    a.download = 'generated_app.py';
    document.body.appendChild(a);
    a.click();
    document.body.removeChild(a);
    URL.revokeObjectURL(url);
  };
  
  return (
    <div className="relative h-full">
      <div className="absolute top-4 right-4 flex items-center gap-2 z-10">
        <button onClick={handleDownload} className="flex items-center gap-2 bg-gray-700 text-white py-2 px-4 rounded-lg hover:bg-gray-600 transition-all duration-200 text-sm font-semibold" aria-label="Download code">
          <DownloadIcon className="w-5 h-5" />
          Download
        </button>
        <button onClick={handleCopy} className="flex items-center gap-2 bg-gray-700 text-white py-2 px-4 rounded-lg hover:bg-gray-600 transition-all duration-200 text-sm font-semibold" aria-label="Copy code">
          <CopyIcon className="w-5 h-5" />
          {copyText}
        </button>
      </div>
      <pre className="h-full w-full overflow-auto p-6 pt-20">
        <code ref={codeRef} className="language-python text-sm font-code whitespace-pre-wrap text-gray-300">
          {finalCode}
        </code>
      </pre>
    </div>
  );
};

type BuildSystem = 'makefile' | 'cmake' | 'meson';

const CppCodeView: React.FC<{ files: Record<string, string> }> = ({ files }) => {
    const [activeFile, setActiveFile] = useState(Object.keys(files)[0] || '');
    const [buildSystem, setBuildSystem] = useState<BuildSystem>('cmake');
    const [isDownloading, setIsDownloading] = useState(false);
    const codeRef = useRef<HTMLElement>(null);

    useEffect(() => {
        // @ts-ignore
        if (window.hljs && codeRef.current) {
            // @ts-ignore
            window.hljs.highlightElement(codeRef.current);
        }
    }, [activeFile, files]);
    
    const getBuildFileContent = (): { filename: string, content: string } => {
        const targetName = "MyApp";
        const sources = Object.keys(files).filter(f => f.endsWith('.cpp')).join(' ');
        const headers = Object.keys(files).filter(f => f.endsWith('.h')).join(' ');

        switch(buildSystem) {
            case 'makefile':
                return {
                    filename: 'Makefile',
                    content: `
CXX = g++
CXXFLAGS = -std=c++17 -fPIC \`pkg-config --cflags Qt6Widgets Qt6Gui Qt6Core Qt6WebEngineWidgets\`
LDFLAGS = \`pkg-config --libs Qt6Widgets Qt6Gui Qt6Core Qt6WebEngineWidgets\`
TARGET = ${targetName}
SOURCES = ${sources}
OBJECTS = $(SOURCES:.cpp=.o)

.PHONY: all clean

all: $(TARGET)

$(TARGET): $(OBJECTS)
\t$(CXX) $(OBJECTS) -o $(TARGET) $(LDFLAGS)

%.o: %.cpp ${headers}
\t$(CXX) $(CXXFLAGS) -c $< -o $@

clean:
\trm -f $(OBJECTS) $(TARGET)
`.trim()
                };
            case 'cmake':
                return {
                    filename: 'CMakeLists.txt',
                    content: `
cmake_minimum_required(VERSION 3.16)
project(${targetName} VERSION 1.0)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_AUTOUIC ON)

find_package(Qt6 COMPONENTS Widgets Gui Core WebEngineWidgets REQUIRED)

add_executable(\${PROJECT_NAME}
    ${sources.split(' ').join('\n    ')}
    ${headers.split(' ').join('\n    ')}
)

target_link_libraries(\${PROJECT_NAME} PRIVATE Qt6::Widgets Qt6::Gui Qt6::Core Qt6::WebEngineWidgets)
`.trim()
                };
            case 'meson':
                return {
                    filename: 'meson.build',
                    content: `
project('${targetName}', 'cpp', version : '1.0', default_options : ['cpp_std=c++17'])

qt6 = dependency('qt6', modules: ['Core', 'Gui', 'Widgets', 'WebEngineWidgets'], required: true)

executable(
    '${targetName}',
    files(${sources.split(' ').map(s=>`'${s}'`).join(', ')}),
    dependencies: [qt6],
    install: true
)
`.trim()
                };
        }
    }

    const handleDownloadZip = async () => {
        setIsDownloading(true);
        const zip = new JSZip();
        
        Object.entries(files).forEach(([name, content]) => {
            zip.file(name, content);
        });

        const buildFile = getBuildFileContent();
        zip.file(buildFile.filename, buildFile.content);
        
        try {
            const content = await zip.generateAsync({type:"blob"});
            const url = URL.createObjectURL(content);
            const a = document.createElement('a');
            a.href = url;
            a.download = 'qt_app.zip';
            document.body.appendChild(a);
            a.click();
            document.body.removeChild(a);
            URL.revokeObjectURL(url);
        } catch (e) {
            console.error("Failed to generate ZIP", e);
        } finally {
            setIsDownloading(false);
        }
    };
    
    if (!activeFile) return <div className="p-4 text-gray-400">No files were generated.</div>

    return (
        <div className="h-full flex flex-col">
            <div className="flex-shrink-0 flex items-center justify-between border-b border-gray-700 p-2 gap-2 flex-wrap">
                <div className="flex items-center gap-1 flex-wrap">
                    {Object.keys(files).map(name => (
                        <button key={name} onClick={() => setActiveFile(name)} className={`px-3 py-2 text-sm rounded-md transition-colors ${activeFile === name ? 'bg-blue-600 text-white font-semibold' : 'bg-gray-800 hover:bg-gray-700 text-gray-300'}`}>
                            {name}
                        </button>
                    ))}
                </div>
            </div>
             <div className="flex-shrink-0 flex items-center justify-end border-b border-gray-700 p-2 gap-2 flex-wrap bg-gray-800/50">
                <div className="flex items-center gap-2">
                    <label htmlFor="build-system" className="text-sm font-medium text-gray-300">Build System:</label>
                    <select id="build-system" value={buildSystem} onChange={e => setBuildSystem(e.target.value as BuildSystem)} className="bg-gray-700 text-white py-2 px-3 rounded-lg text-sm font-semibold border-0 focus:ring-2 focus:ring-blue-500">
                        <option value="cmake">CMake</option>
                        <option value="makefile">Makefile</option>
                        <option value="meson">Meson</option>
                    </select>
                </div>
                <button onClick={handleDownloadZip} disabled={isDownloading} className="flex items-center gap-2 bg-green-600 text-white py-2 px-4 rounded-lg hover:bg-green-500 transition-all duration-200 text-sm font-semibold disabled:bg-gray-500">
                    <DownloadIcon className="w-5 h-5" />
                    {isDownloading ? 'Zipping...' : 'Download ZIP'}
                </button>
            </div>
            <div className="relative flex-grow overflow-hidden">
                <pre className="h-full w-full overflow-auto p-6">
                  <code ref={codeRef} className="language-cpp text-sm font-code whitespace-pre-wrap text-gray-300">
                    {files[activeFile]}
                  </code>
                </pre>
            </div>
        </div>
    );
};


const CodeDisplay: React.FC<CodeDisplayProps> = ({ appType, pythonCode, cppFiles, status }) => {
  if (status !== AppStatus.SUCCESS) {
    return <div className="p-4">Generating...</div>;
  }
  
  return (
    <div className="h-full flex flex-col bg-gray-900 rounded-b-2xl">
      {appType === 'python' && pythonCode ? (
        <PythonCodeView code={pythonCode} />
      ) : appType === 'c++' && cppFiles ? (
        <CppCodeView files={cppFiles} />
      ) : (
        <div className="p-4 text-gray-400">Code generation complete, but no output received.</div>
      )}
    </div>
  );
};

export default CodeDisplay;