import React, { useState, useCallback, useEffect, useRef } from 'react';
import type { AppState, CompetitorCandidate, Product, TargetIndustry, Keyword, SilverBullet, Battlecard, ReferenceAnalysis } from './types';
import { fetchStep1Data, fetchStep2Data, fetchStep3Data, fetchStep4Data, fetchStep5Data_SilverBullets, fetchStep6Data_Conclusion, fetchStep7Data_Battlecards, fetchStep8Data_ReferenceAnalysis } from './services/geminiService';
import { generatePdfReport } from './services/pdfService';
import InputForm from './components/InputForm';
import StepIndicator from './components/StepIndicator';
import Step1Extraction from './components/Step1_Extraction';
import Step2Keywords from './components/Step2_Keywords';
import Step3Competitors from './components/Step3_Competitors';
import Step4Analysis from './components/Step4_Analysis';
import Step5SilverBullets from './components/Step5_SilverBullets';
import Step6Conclusion from './components/Step6_Conclusion';
import Step7_Battlecards from './components/Step7_Battlecards';
import Step8_References from './components/Step8_References';
import LoadingSpinner from './components/LoadingSpinner';
import { translations } from './translations';

const SunIcon = () => (<svg xmlns="http://www.w3.org/2000/svg" className="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 3v1m0 16v1m9-9h-1M4 12H3m15.364 6.364l-.707-.707M6.343 6.343l-.707-.707m12.728 0l-.707.707M6.343 17.657l-.707.707M16 12a4 4 0 11-8 0 4 4 0 018 0z" /></svg>);
const MoonIcon = () => (<svg xmlns="http://www.w3.org/2000/svg" className="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M20.354 15.354A9 9 0 018.646 3.646 9.003 9.003 0 0012 21a9.003 9.003 0 008.354-5.646z" /></svg>);
const RestartIcon = () => (<svg xmlns="http://www.w3.org/2000/svg" className="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2}><path strokeLinecap="round" strokeLinejoin="round" d="M4 4v5h5M4 12a9 9 0 109-9" /></svg>);
const DownloadIcon = () => (<svg xmlns="http://www.w3.org/2000/svg" className="h-5 w-5 mr-2" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4" /></svg>);
const ChevronDownIcon = () => (<svg className="w-5 h-5 ml-2 -mr-1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true"><path fillRule="evenodd" d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z" clipRule="evenodd" /></svg>);


const App: React.FC = () => {
    const [appState, setAppState] = useState<AppState | null>(null);
    const [isLoading, setIsLoading] = useState<boolean>(false);
    const [error, setError] = useState<string | null>(null);
    const [theme, setTheme] = useState<'light' | 'dark'>('dark');
    const [highestStep, setHighestStep] = useState(0);
    const [isDropdownOpen, setIsDropdownOpen] = useState(false);
    const dropdownRef = useRef<HTMLDivElement>(null);

    const t = translations[appState?.initial_params?.language || 'de'];

    useEffect(() => {
        if (theme === 'dark') {
            document.documentElement.classList.add('dark');
        } else {
            document.documentElement.classList.remove('dark');
        }
    }, [theme]);

    useEffect(() => {
        const handleClickOutside = (event: MouseEvent) => {
            if (dropdownRef.current && !dropdownRef.current.contains(event.target as Node)) {
                setIsDropdownOpen(false);
            }
        };
        document.addEventListener("mousedown", handleClickOutside);
        return () => document.removeEventListener("mousedown", handleClickOutside);
    }, []);

    const handleRestart = () => {
        setAppState(null);
        setIsLoading(false);
        setError(null);
        setHighestStep(0);
    };

    const handleStartAnalysis = useCallback(async (startUrl: string, maxCompetitors: number, marketScope: string, language: 'de' | 'en') => {
        setIsLoading(true);
        setError(null);
        setAppState(null);
        setHighestStep(0);
        const currentT = translations[language];
        try {
            const { products, target_industries } = await fetchStep1Data(startUrl, language);
            setAppState({
                step: 1,
                initial_params: { start_url: startUrl, max_competitors: maxCompetitors, market_scope: marketScope, language },
                company: { name: new URL(startUrl).hostname.replace('www.', ''), start_url: startUrl },
                products: products,
                target_industries: target_industries,
                keywords: [],
                competitor_candidates: [],
                competitors_shortlist: [],
                analyses: [],
                silver_bullets: [],
                conclusion: null,
                battlecards: [],
                reference_analysis: [],
                reference_analysis_grounding: [],
            });
            setHighestStep(1);
        } catch (e) {
            console.error("Error in Step 1:", e);
            setError(currentT.errors.step1);
        } finally {
            setIsLoading(false);
        }
    }, []);

    const handleConfirmStep = useCallback(async () => {
        if (!appState) return;

        setIsLoading(true);
        setError(null);
        const nextStep = appState.step + 1;
        const lang = appState.initial_params.language;
        try {
            let newState: Partial<AppState> = {};
            switch (appState.step) {
                case 1:
                    const { keywords } = await fetchStep2Data(appState.products, appState.target_industries, lang);
                    newState = { keywords, step: 2 };
                    break;
                case 2:
                    const { competitor_candidates } = await fetchStep3Data(appState.keywords, appState.initial_params.market_scope, lang);
                    newState = { competitor_candidates, step: 3 };
                    break;
                case 3:
                    const shortlist = [...appState.competitor_candidates]
                        .sort((a, b) => b.confidence - a.confidence)
                        .slice(0, appState.initial_params.max_competitors);
                    const { analyses } = await fetchStep4Data(appState.company, shortlist, lang);
                    newState = { competitors_shortlist: shortlist, analyses, step: 4 };
                    break;
                case 4:
                    const { silver_bullets } = await fetchStep5Data_SilverBullets(appState.company, appState.analyses, lang);
                    newState = { silver_bullets, step: 5 };
                    break;
                case 5:
                    const { conclusion } = await fetchStep6Data_Conclusion(appState.company, appState.products, appState.target_industries, appState.analyses, appState.silver_bullets, lang);
                    newState = { conclusion, step: 6 };
                    break;
                case 6:
                     const { battlecards } = await fetchStep7Data_Battlecards(appState.company, appState.analyses, appState.silver_bullets, lang);
                    newState = { battlecards, step: 7 };
                    break;
                case 7:
                    const { reference_analysis, groundingMetadata } = await fetchStep8Data_ReferenceAnalysis(appState.competitors_shortlist, lang);
                    newState = { reference_analysis, reference_analysis_grounding: groundingMetadata, step: 8 };
                    break;
            }
            setAppState(prevState => ({ ...prevState!, ...newState }));
            if (nextStep > highestStep) {
                setHighestStep(nextStep);
            }
        } catch (e) {
            console.error(`Error in Step ${appState.step + 1}:`, e);
            setError(translations[lang].errors.generic(appState.step + 1));
        } finally {
            setIsLoading(false);
        }
    }, [appState, highestStep]);

    const handleUpdateState = useCallback((key: keyof AppState, value: any) => {
        setAppState(prevState => {
            if (!prevState) return null;
            return { ...prevState, [key]: value };
        });
    }, []);

    const renderStepContent = () => {
        if (!appState) return null;
        switch (appState.step) {
            case 1: return <Step1Extraction products={appState.products} industries={appState.target_industries} onProductsChange={(p) => handleUpdateState('products', p)} onIndustriesChange={(i) => handleUpdateState('target_industries', i)} t={t.step1} lang={appState.initial_params.language} />;
            case 2: return <Step2Keywords keywords={appState.keywords} onKeywordsChange={(k) => handleUpdateState('keywords', k)} t={t.step2} />;
            case 3: return <Step3Competitors candidates={appState.competitor_candidates} onCandidatesChange={(c) => handleUpdateState('competitor_candidates', c)} maxCompetitors={appState.initial_params.max_competitors} t={t.step3} />;
            case 4: return <Step4Analysis analyses={appState.analyses} t={t.step4} />;
            case 5: return <Step5SilverBullets silver_bullets={appState.silver_bullets} t={t.step5} />;
            case 6: return <Step6Conclusion appState={appState} t={t.step6} />;
            case 7: return <Step7_Battlecards appState={appState} t={t.step7} />;
            case 8: return <Step8_References analyses={appState.reference_analysis} groundingMetadata={appState.reference_analysis_grounding} t={t.step8} />;
            default: return null;
        }
    };
    
    // Download logic
    const handleDownloadJson = () => {
        if (!appState) return;
        const content = JSON.stringify(appState, null, 2);
        const blob = new Blob([content], { type: 'application/json' });
        const url = URL.createObjectURL(blob);
        const link = document.createElement('a');
        link.href = url;
        link.download = `analysis_${appState.company.name}.json`;
        document.body.appendChild(link);
        link.click();
        document.body.removeChild(link);
        URL.revokeObjectURL(url);
        setIsDropdownOpen(false);
    };

    const transformMatrixData = (matrixData: any[] | undefined): { [row: string]: { [col: string]: string } } => {
        const tableData: { [row: string]: { [col: string]: string } } = {};
        if (!matrixData || !Array.isArray(matrixData) || matrixData.length === 0) {
            return tableData;
        }

        const allCompetitors = new Set<string>();
        matrixData.forEach(row => {
            if (row && Array.isArray(row.availability)) {
                row.availability.forEach(item => {
                    if (item && typeof item.competitor === 'string') {
                        allCompetitors.add(item.competitor);
                    }
                });
            }
        });
        const competitorList = Array.from(allCompetitors).sort(); 

        matrixData.forEach(row => {
            if (!row) return;
            
            const rowKey = 'product' in row ? row.product : ('industry' in row ? row.industry : undefined);

            if (typeof rowKey !== 'string' || !rowKey) {
                return;
            }
            
            const availabilityMap = new Map<string, boolean>();
            if (Array.isArray(row.availability)) {
                 row.availability.forEach(item => {
                    if (item && typeof item.competitor === 'string') {
                        availabilityMap.set(item.competitor, item.has_offering);
                    }
                });
            }
            
            const rowObject: { [col: string]: string } = {};
            competitorList.forEach(competitor => {
                rowObject[competitor] = availabilityMap.get(competitor) ? '✓' : ' ';
            });
            tableData[rowKey] = rowObject;
        });

        return tableData;
    };


    const generateMarkdownReport = (): string => {
        if (!appState) return "";
        const langT = t.step6.markdown;
        let md = `# ${langT.title}: ${appState.company.name}\n\n`;
        md += `**${langT.startUrl}:** ${appState.initial_params.start_url}\n`;
        md += `**${langT.marketScope}:** ${appState.initial_params.market_scope}\n\n`;

        md += `## ${langT.step1_title}\n`;
        md += `### ${langT.step1_products}\n`;
        appState.products.forEach(p => md += `- **${p.name}:** ${p.purpose}\n`);
        md += `\n### ${langT.step1_industries}\n`;
        appState.target_industries.forEach(i => md += `- ${i.name}\n`);

        md += `\n## ${langT.step4_title}\n`;
        appState.analyses.forEach(a => {
            md += `### ${a.competitor.name} (Overlap: ${a.overlap_score}%)\n`;
            md += `- **${langT.portfolio}:** ${a.portfolio.map(p => p.product).join(', ')}\n`;
            md += `- **${langT.targetIndustries}:** ${a.target_industries.join(', ')}\n`;
            md += `- **${langT.differentiators}:**\n`;
            a.differentiators.forEach(d => md += `  - ${d}\n`);
            md += `\n`;
        });

        md += `## ${langT.step5_title}\n`;
        appState.silver_bullets.forEach(b => {
             md += `- **${langT.against} ${b.competitor_name}:** "${b.statement}"\n`;
        });

        if (appState.battlecards && appState.battlecards.length > 0) {
            md += `\n## ${langT.step7_title}\n\n`;
            appState.battlecards.forEach(card => {
                md += `### ${langT.against} ${card.competitor_name}\n\n`;
                md += `**${langT.profile}:**\n`;
                md += `- **${langT.focus}:** ${card.competitor_profile.focus}\n`;
                md += `- **${langT.positioning}:** ${card.competitor_profile.positioning}\n\n`;

                md += `**${langT.strengthsVsWeaknesses}:**\n`;
                (card.strengths_vs_weaknesses || []).forEach(s => md += `- ${s}\n`);
                md += `\n`;

                md += `**${langT.landmineQuestions}:**\n`;
                (card.landmine_questions || []).forEach(q => md += `- ${q}\n`);
                md += `\n`;
                
                md += `**${langT.silverBullet}:**\n`;
                md += `> "${card.silver_bullet}"\n\n`;
            });
        }

        if (appState.reference_analysis && appState.reference_analysis.length > 0) {
            md += `\n## ${langT.step8_title}\n`;
            appState.reference_analysis.forEach(analysis => {
                md += `### ${analysis.competitor_name}\n`;
                if ((analysis.references || []).length > 0) {
                    (analysis.references || []).forEach(ref => {
                        md += `- **${ref.name}** (${ref.industry || 'N/A'})\n`;
                        if(ref.testimonial_snippet) md += `  - *"${ref.testimonial_snippet}"*\n`;
                        if(ref.case_study_url) md += `  - [${langT.caseStudyLink}](${ref.case_study_url})\n`;
                    });
                } else {
                    md += `  - ${langT.noReferencesFound}\n`;
                }
                md += `\n`;
            });
            if (appState.reference_analysis_grounding && appState.reference_analysis_grounding.length > 0) {
                 md += `\n#### ${langT.sources}\n`;
                 appState.reference_analysis_grounding
                    .filter(chunk => chunk.web && chunk.web.uri)
                    .forEach(chunk => {
                        md += `- [${chunk.web.title || chunk.web.uri}](${chunk.web.uri})\n`;
                    });
            }
        }
        
        if(appState.conclusion) {
            md += `\n## ${langT.step6_title}\n`;
            const transformForMdTable = (data: { [key: string]: { [key: string]: string } }) => {
                if (Object.keys(data).length === 0) return { head: '', body: '' };
                const headers = Object.keys(Object.values(data)[0] || {});
                const head = `| | ${headers.join(' | ')} |\n`;
                const separator = `|---|${headers.map(() => '---').join('|')}|\n`;
                const body = Object.entries(data).map(([row, cols]) => `| **${row}** | ${headers.map(h => cols[h] || ' ').join(' | ')} |`).join('\n');
                return { head, body: separator + body };
            };
            const productMatrixForTable = transformMatrixData(appState.conclusion.product_matrix);
            const industryMatrixForTable = transformMatrixData(appState.conclusion.industry_matrix);

            md += `### ${langT.productMatrix}\n`;
            const prodMd = transformForMdTable(productMatrixForTable);
            md += prodMd.head + prodMd.body + '\n\n';

            md += `### ${langT.industryMatrix}\n`;
            const indMd = transformForMdTable(industryMatrixForTable);
            md += indMd.head + indMd.body + '\n\n';

            md += `### ${langT.summary}\n${appState.conclusion.summary}\n\n`;
            md += `### ${langT.opportunities}\n${appState.conclusion.opportunities}\n\n`;
            md += `### ${langT.nextQuestions}\n`;
            (appState.conclusion.next_questions || []).forEach(q => md += `- ${q}\n`);
        }
        
        return md;
    };
    
    const handleDownloadMd = () => {
        const mdContent = generateMarkdownReport();
        const blob = new Blob([mdContent], { type: 'text/markdown' });
        const url = URL.createObjectURL(blob);
        const link = document.createElement('a');
        link.href = url;
        if (appState) {
            link.download = `analysis_${appState.company.name}.md`;
        }
        document.body.appendChild(link);
        link.click();
        document.body.removeChild(link);
        URL.revokeObjectURL(url);
        setIsDropdownOpen(false);
    };
    
    const handleDownloadPdf = async () => {
        if (!appState) return;
        await generatePdfReport(appState, t.step6.markdown);
        setIsDropdownOpen(false);
    };
    
    return (
        <div className="min-h-screen p-4 sm:p-6 lg:p-8">
            <header className="flex justify-between items-center mb-6">
                <h1 className="text-3xl font-bold">{t.appTitle}</h1>
                <div className="flex items-center space-x-4">
                    {appState && highestStep >= 6 && (
                        <div className="relative inline-block text-left" ref={dropdownRef}>
                            <div>
                                <button
                                    type="button"
                                    onClick={() => setIsDropdownOpen(!isDropdownOpen)}
                                    className="inline-flex justify-center w-full rounded-lg border border-transparent shadow-sm px-4 py-2 bg-green-600 text-base font-medium text-white hover:bg-green-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-offset-light-secondary dark:focus:ring-offset-brand-secondary focus:ring-green-500"
                                >
                                    <DownloadIcon />
                                    {t.step6.downloadButton}
                                    <ChevronDownIcon />
                                </button>
                            </div>
                            {isDropdownOpen && (
                                <div className="origin-top-right absolute right-0 mt-2 w-56 rounded-md shadow-lg bg-light-secondary dark:bg-brand-secondary ring-1 ring-black ring-opacity-5 z-20">
                                    <div className="py-1" role="menu" aria-orientation="vertical" aria-labelledby="options-menu">
                                        <a href="#" onClick={(e) => { e.preventDefault(); handleDownloadJson(); }} className="block px-4 py-2 text-sm text-light-text dark:text-brand-text hover:bg-light-accent dark:hover:bg-brand-accent" role="menuitem">{t.step6.downloadJson}</a>
                                        <a href="#" onClick={(e) => { e.preventDefault(); handleDownloadMd(); }} className="block px-4 py-2 text-sm text-light-text dark:text-brand-text hover:bg-light-accent dark:hover:bg-brand-accent" role="menuitem">{t.step6.downloadMd}</a>
                                        <a href="#" onClick={(e) => { e.preventDefault(); handleDownloadPdf(); }} className="block px-4 py-2 text-sm text-light-text dark:text-brand-text hover:bg-light-accent dark:hover:bg-brand-accent" role="menuitem">{t.step6.downloadPdf}</a>
                                    </div>
                                </div>
                            )}
                        </div>
                    )}
                     {appState && (
                        <button onClick={handleRestart} className="p-2 rounded-full hover:bg-light-accent dark:hover:bg-brand-accent" title={t.restartAnalysis}>
                            <RestartIcon />
                        </button>
                    )}
                    <button onClick={() => setTheme(theme === 'dark' ? 'light' : 'dark')} className="p-2 rounded-full hover:bg-light-accent dark:hover:bg-brand-accent">
                        {theme === 'dark' ? <SunIcon /> : <MoonIcon />}
                    </button>
                </div>
            </header>

            <main className="mx-auto">
                {!appState && !isLoading && <InputForm onStart={handleStartAnalysis} />}
                
                {isLoading && !appState && <LoadingSpinner t={t.loadingSpinner} />}

                {appState && (
                    <div className="grid grid-cols-1 lg:grid-cols-4 gap-8 items-start">
                        <aside className="lg:col-span-1 lg:sticky lg:top-8">
                           <div className="bg-light-secondary dark:bg-brand-secondary p-4 rounded-lg shadow-md mb-6">
                                <h3 className="font-bold text-lg mb-2">{t.companyCard.title}</h3>
                                <p className="text-sm break-words">{appState.company.name}</p>
                           </div>
                           <StepIndicator 
                                currentStep={appState.step} 
                                highestStep={highestStep}
                                onStepClick={(step) => setAppState(prevState => ({...prevState!, step}))}
                                t={t.stepIndicator}
                            />
                        </aside>

                        <div className="lg:col-span-3">
                            <div className="min-h-[400px]">
                                {error && (
                                    <div className="bg-red-100 border-l-4 border-red-500 text-red-700 p-4 rounded-lg mb-6" role="alert">
                                        <p className="font-bold">{t.errors.title}</p>
                                        <p>{error}</p>
                                    </div>
                                )}
                                {isLoading ? <LoadingSpinner t={t.loadingSpinner} /> : renderStepContent()}
                            </div>
                            
                            {appState.step < 8 && !isLoading && (
                                <div className="mt-8 text-right">
                                    <button
                                        onClick={handleConfirmStep}
                                        className="bg-brand-highlight hover:bg-blue-600 text-white font-bold py-3 px-6 rounded-lg shadow-lg transition duration-300 transform hover:scale-105"
                                    >
                                        {t.nextStepButton}
                                    </button>
                                </div>
                            )}
                        </div>
                    </div>
                )}
            </main>
        </div>
    );
};

export default App;