/**
 * Unified Vaccine Data Generator
 *
 * Generates realistic, geographically accurate Point-based GeoJSON data
 * for vaccine visualization globe demos. Uses country centroids and
 * realistic metric generation.
 */

/**
 * Country centroids and metadata (WHO regions, income levels)
 * This is a curated list of major countries with accurate geographic centers
 */
const COUNTRY_DATA = [
    // Africa (AFRO)
    { name: 'Nigeria', iso3: 'NGA', centroid: [8.6753, 9.0820], region: 'AFRO', income: 'lower-middle', population: 218541000 },
    { name: 'Ethiopia', iso3: 'ETH', centroid: [40.4897, 9.1450], region: 'AFRO', income: 'low', population: 123379000 },
    { name: 'Egypt', iso3: 'EGY', centroid: [30.8025, 26.8206], region: 'AFRO', income: 'lower-middle', population: 109262000 },
    { name: 'Democratic Republic of the Congo', iso3: 'COD', centroid: [21.7587, -4.0383], region: 'AFRO', income: 'low', population: 99010000 },
    { name: 'South Africa', iso3: 'ZAF', centroid: [22.9375, -30.5595], region: 'AFRO', income: 'upper-middle', population: 60041000 },
    { name: 'Tanzania', iso3: 'TZA', centroid: [34.8888, -6.3690], region: 'AFRO', income: 'lower-middle', population: 65497000 },
    { name: 'Kenya', iso3: 'KEN', centroid: [37.9062, -0.0236], region: 'AFRO', income: 'lower-middle', population: 54027000 },
    { name: 'Uganda', iso3: 'UGA', centroid: [32.2903, 1.3733], region: 'AFRO', income: 'low', population: 47249000 },
    { name: 'Algeria', iso3: 'DZA', centroid: [1.6596, 28.0339], region: 'AFRO', income: 'lower-middle', population: 44903000 },
    { name: 'Sudan', iso3: 'SDN', centroid: [30.2176, 12.8628], region: 'AFRO', income: 'low', population: 46874000 },
    { name: 'Morocco', iso3: 'MAR', centroid: [-7.0926, 31.7917], region: 'AFRO', income: 'lower-middle', population: 37457000 },
    { name: 'Ghana', iso3: 'GHA', centroid: [-1.0232, 7.9465], region: 'AFRO', income: 'lower-middle', population: 33476000 },
    { name: 'Mozambique', iso3: 'MOZ', centroid: [35.5296, -18.6657], region: 'AFRO', income: 'low', population: 32969000 },
    { name: 'Madagascar', iso3: 'MDG', centroid: [46.8691, -18.7669], region: 'AFRO', income: 'low', population: 29611000 },
    { name: 'Cameroon', iso3: 'CMR', centroid: [12.3547, 7.3697], region: 'AFRO', income: 'lower-middle', population: 27914000 },

    // Eastern Mediterranean (EMRO)
    { name: 'Pakistan', iso3: 'PAK', centroid: [69.3451, 30.3753], region: 'EMRO', income: 'lower-middle', population: 235825000 },
    { name: 'Iran', iso3: 'IRN', centroid: [53.6880, 32.4279], region: 'EMRO', income: 'lower-middle', population: 88550000 },
    { name: 'Saudi Arabia', iso3: 'SAU', centroid: [45.0792, 23.8859], region: 'EMRO', income: 'high', population: 36409000 },
    { name: 'Yemen', iso3: 'YEM', centroid: [48.5164, 15.5527], region: 'EMRO', income: 'low', population: 33697000 },
    { name: 'Iraq', iso3: 'IRQ', centroid: [43.6793, 33.2232], region: 'EMRO', income: 'upper-middle', population: 44496000 },
    { name: 'Afghanistan', iso3: 'AFG', centroid: [67.7100, 33.9391], region: 'EMRO', income: 'low', population: 41129000 },
    { name: 'Morocco', iso3: 'MAR', centroid: [-7.0926, 31.7917], region: 'EMRO', income: 'lower-middle', population: 37457000 },
    { name: 'Somalia', iso3: 'SOM', centroid: [46.1996, 5.1521], region: 'EMRO', income: 'low', population: 17597000 },

    // Europe (EURO)
    { name: 'Russia', iso3: 'RUS', centroid: [105.3188, 61.5240], region: 'EURO', income: 'upper-middle', population: 144713000 },
    { name: 'Germany', iso3: 'DEU', centroid: [10.4515, 51.1657], region: 'EURO', income: 'high', population: 83294000 },
    { name: 'United Kingdom', iso3: 'GBR', centroid: [-3.4360, 55.3781], region: 'EURO', income: 'high', population: 67736000 },
    { name: 'France', iso3: 'FRA', centroid: [2.2137, 46.2276], region: 'EURO', income: 'high', population: 64626000 },
    { name: 'Italy', iso3: 'ITA', centroid: [12.5674, 41.8719], region: 'EURO', income: 'high', population: 58983000 },
    { name: 'Spain', iso3: 'ESP', centroid: [-3.7492, 40.4637], region: 'EURO', income: 'high', population: 47778000 },
    { name: 'Ukraine', iso3: 'UKR', centroid: [31.1656, 48.3794], region: 'EURO', income: 'lower-middle', population: 43814000 },
    { name: 'Poland', iso3: 'POL', centroid: [19.1451, 51.9194], region: 'EURO', income: 'high', population: 38307000 },
    { name: 'Romania', iso3: 'ROU', centroid: [24.9668, 45.9432], region: 'EURO', income: 'upper-middle', population: 19064000 },
    { name: 'Netherlands', iso3: 'NLD', centroid: [5.2913, 52.1326], region: 'EURO', income: 'high', population: 17564000 },

    // Americas (PAHO)
    { name: 'United States', iso3: 'USA', centroid: [-95.7129, 37.0902], region: 'PAHO', income: 'high', population: 339996000 },
    { name: 'Brazil', iso3: 'BRA', centroid: [-51.9253, -14.2350], region: 'PAHO', income: 'upper-middle', population: 216422000 },
    { name: 'Mexico', iso3: 'MEX', centroid: [-102.5528, 23.6345], region: 'PAHO', income: 'upper-middle', population: 128456000 },
    { name: 'Colombia', iso3: 'COL', centroid: [-74.2973, 4.5709], region: 'PAHO', income: 'upper-middle', population: 52085000 },
    { name: 'Argentina', iso3: 'ARG', centroid: [-63.6167, -38.4161], region: 'PAHO', income: 'upper-middle', population: 45510000 },
    { name: 'Canada', iso3: 'CAN', centroid: [-106.3468, 56.1304], region: 'PAHO', income: 'high', population: 38781000 },
    { name: 'Peru', iso3: 'PER', centroid: [-75.0152, -9.1900], region: 'PAHO', income: 'upper-middle', population: 34352000 },
    { name: 'Venezuela', iso3: 'VEN', centroid: [-66.5897, 6.4238], region: 'PAHO', income: 'upper-middle', population: 28302000 },
    { name: 'Chile', iso3: 'CHL', centroid: [-71.5430, -35.6751], region: 'PAHO', income: 'high', population: 19603000 },
    { name: 'Guatemala', iso3: 'GTM', centroid: [-90.2308, 15.7835], region: 'PAHO', income: 'upper-middle', population: 18092000 },
    { name: 'Haiti', iso3: 'HTI', centroid: [-72.2852, 18.9712], region: 'PAHO', income: 'low', population: 11584000 },

    // South-East Asia (SEARO)
    { name: 'India', iso3: 'IND', centroid: [78.9629, 20.5937], region: 'SEARO', income: 'lower-middle', population: 1428627000 },
    { name: 'Indonesia', iso3: 'IDN', centroid: [113.9213, -0.7893], region: 'SEARO', income: 'lower-middle', population: 277534000 },
    { name: 'Bangladesh', iso3: 'BGD', centroid: [90.3563, 23.6850], region: 'SEARO', income: 'lower-middle', population: 172954000 },
    { name: 'Thailand', iso3: 'THA', centroid: [100.9925, 15.8700], region: 'SEARO', income: 'upper-middle', population: 71801000 },
    { name: 'Myanmar', iso3: 'MMR', centroid: [95.9560, 21.9162], region: 'SEARO', income: 'lower-middle', population: 54577000 },
    { name: 'Sri Lanka', iso3: 'LKA', centroid: [80.7718, 7.8731], region: 'SEARO', income: 'lower-middle', population: 22181000 },
    { name: 'Nepal', iso3: 'NPL', centroid: [84.1240, 28.3949], region: 'SEARO', income: 'lower-middle', population: 30547000 },

    // Western Pacific (WPRO)
    { name: 'China', iso3: 'CHN', centroid: [104.1954, 35.8617], region: 'WPRO', income: 'upper-middle', population: 1425671000 },
    { name: 'Philippines', iso3: 'PHL', centroid: [121.7740, 12.8797], region: 'WPRO', income: 'lower-middle', population: 117337000 },
    { name: 'Japan', iso3: 'JPN', centroid: [138.2529, 36.2048], region: 'WPRO', income: 'high', population: 123294000 },
    { name: 'Vietnam', iso3: 'VNM', centroid: [108.2772, 14.0583], region: 'WPRO', income: 'lower-middle', population: 98859000 },
    { name: 'South Korea', iso3: 'KOR', centroid: [127.7669, 35.9078], region: 'WPRO', income: 'high', population: 51784000 },
    { name: 'Australia', iso3: 'AUS', centroid: [133.7751, -25.2744], region: 'WPRO', income: 'high', population: 26439000 },
    { name: 'Malaysia', iso3: 'MYS', centroid: [101.9758, 4.2105], region: 'WPRO', income: 'upper-middle', population: 34308000 },
    { name: 'Cambodia', iso3: 'KHM', centroid: [104.9910, 12.5657], region: 'WPRO', income: 'lower-middle', population: 16944000 },
    { name: 'Papua New Guinea', iso3: 'PNG', centroid: [143.9555, -6.3150], region: 'WPRO', income: 'lower-middle', population: 10329000 },
    { name: 'New Zealand', iso3: 'NZL', centroid: [174.8860, -40.9006], region: 'WPRO', income: 'high', population: 5228000 }
];

/**
 * Vaccine Data Generator Class
 */
export class VaccineDataGenerator {
    constructor(vaccineType) {
        this.vaccineType = vaccineType;
        this.countries = COUNTRY_DATA;
    }

    /**
     * Generate complete GeoJSON FeatureCollection
     * @returns {Object} GeoJSON FeatureCollection with Point features
     */
    generateData() {
        return {
            type: 'FeatureCollection',
            features: this.countries.map(country => this.generateFeature(country))
        };
    }

    /**
     * Generate a single GeoJSON feature for a country
     * @param {Object} country - Country metadata
     * @returns {Object} GeoJSON Feature
     */
    generateFeature(country) {
        return {
            type: 'Feature',
            geometry: {
                type: 'Point',
                coordinates: country.centroid // [lng, lat]
            },
            properties: {
                name: country.name,
                iso3: country.iso3,
                region: country.region,
                income_level: country.income,
                population: country.population,
                ...this.generateVaccineMetrics(country)
            }
        };
    }

    /**
     * Generate vaccine-specific metrics based on type
     * @param {Object} country - Country metadata
     * @returns {Object} Vaccine-specific properties
     */
    generateVaccineMetrics(country) {
        const generators = {
            polio: () => this.generatePolioMetrics(country),
            measles: () => this.generateMeaslesMetrics(country),
            smallpox: () => this.generateSmallpoxMetrics(country),
            dtp3: () => this.generateDTP3Metrics(country),
            hpv: () => this.generateHPVMetrics(country)
        };

        return generators[this.vaccineType]?.() || {};
    }

    /**
     * Polio-specific metrics
     */
    generatePolioMetrics(country) {
        const baseCoverage1980 = this.getBaseCoverage(country, 1980);
        const baseCoverage2020 = this.getBaseCoverage(country, 2020);

        return {
            coverage_1980: baseCoverage1980,
            coverage_1985: this.interpolate(baseCoverage1980, baseCoverage2020, 0.125),
            coverage_1990: this.interpolate(baseCoverage1980, baseCoverage2020, 0.25),
            coverage_1995: this.interpolate(baseCoverage1980, baseCoverage2020, 0.375),
            coverage_2000: this.interpolate(baseCoverage1980, baseCoverage2020, 0.5),
            coverage_2005: this.interpolate(baseCoverage1980, baseCoverage2020, 0.625),
            coverage_2010: this.interpolate(baseCoverage1980, baseCoverage2020, 0.75),
            coverage_2015: this.interpolate(baseCoverage1980, baseCoverage2020, 0.875),
            coverage_2020: baseCoverage2020,
            polio_free_year: this.getPolioFreeYear(country),
            endemic: this.isPolioEndemic(country)
        };
    }

    /**
     * Measles-specific metrics
     */
    generateMeaslesMetrics(country) {
        const dose1 = this.getMeaslesCoverage(country, 'dose1');
        const dose2 = this.getMeaslesCoverage(country, 'dose2');

        return {
            coverage_dose1: dose1,
            coverage_dose2: dose2,
            cases_2023: this.calculateMeaslesCases(country, dose1),
            deaths_2023: this.calculateMeaslesDeaths(country, dose1)
        };
    }

    /**
     * Smallpox-specific metrics (historical)
     */
    generateSmallpoxMetrics(country) {
        return {
            endemic_1950: this.wasEndemicIn1950(country),
            endemic_1960: this.wasEndemicIn1960(country),
            endemic_1970: this.wasEndemicIn1970(country),
            endemic_1980: false, // Eradicated by 1980
            eradication_year: this.getEradicationYear(country),
            last_case_year: this.getLastCaseYear(country),
            vaccination_intensity: this.getVaccinationIntensity(country),
            cases_peak_year: this.random(1950, 1970),
            cases_peak: this.random(10000, 500000)
        };
    }

    /**
     * DTP3-specific metrics
     */
    generateDTP3Metrics(country) {
        const coverage2024 = this.getDTP3Coverage(country);
        const coverage1974 = this.random(5, 30);

        return {
            dtp3_coverage_2024: coverage2024,
            dtp3_coverage_1974: coverage1974,
            zero_dose_children: this.calculateZeroDose(country, coverage2024),
            under5_mortality_rate: this.calculateMortality(country, coverage2024),
            infant_deaths_prevented: this.calculateLivesSaved(country, coverage2024, coverage1974),
            population_under1: Math.round(country.population * 0.012) // ~1.2% birth rate
        };
    }

    /**
     * HPV-specific metrics
     */
    generateHPVMetrics(country) {
        const coverage = this.getHPVCoverage(country);

        return {
            hpv_coverage_2024: coverage,
            vaccine_program_started: coverage > 0 ? this.random(2008, 2020) : null,
            target_age: '9-14',
            cervical_cancer_incidence: this.getCervicalCancerRate(country, coverage),
            cervical_cancer_mortality: this.getCervicalCancerMortality(country, coverage),
            lives_saved_projected: this.calculateHPVLivesSaved(country, coverage),
            gender_policy: this.random(0, 100) > 30 ? 'girls-only' : 'girls-and-boys',
            annual_deaths: this.calculateAnnualDeaths(country, coverage)
        };
    }

    // ===== HELPER METHODS =====

    /**
     * Get base vaccine coverage based on income and region
     */
    getBaseCoverage(country, year) {
        let base = 50;

        // Income level adjustments
        if (country.income === 'high') base += 30;
        else if (country.income === 'upper-middle') base += 20;
        else if (country.income === 'lower-middle') base += 5;
        else base -= 10;

        // Year adjustments (coverage improved over time)
        if (year >= 2010) base += 20;
        else if (year >= 2000) base += 15;
        else if (year >= 1990) base += 10;
        else if (year >= 1980) base += 5;

        // Regional variations
        if (country.region === 'EURO' || country.region === 'PAHO') base += 10;
        if (country.region === 'AFRO') base -= 5;

        // Add randomness
        base += this.random(-8, 8);

        return Math.max(5, Math.min(99, Math.round(base)));
    }

    getDTP3Coverage(country) {
        return this.getBaseCoverage(country, 2024);
    }

    getMeaslesCoverage(country, dose) {
        const base = this.getBaseCoverage(country, 2023);
        if (dose === 'dose2') {
            return Math.round(base * 0.85); // Dose 2 typically lower
        }
        return base;
    }

    getHPVCoverage(country) {
        // HPV coverage is generally lower and more variable
        let coverage = this.getBaseCoverage(country, 2024) * 0.7;

        // Some low-income countries have no program
        if (country.income === 'low' && this.random(0, 100) > 40) {
            coverage = 0;
        }

        return Math.round(coverage);
    }

    /**
     * Calculate derived metrics
     */
    calculateZeroDose(country, coverage) {
        const birthCohort = Math.round(country.population * 0.012);
        return Math.round(birthCohort * (100 - coverage) / 100);
    }

    calculateMortality(country, coverage) {
        // Lower coverage = higher mortality
        let baseMortality = 50;

        if (country.income === 'high') baseMortality = 5;
        else if (country.income === 'upper-middle') baseMortality = 15;
        else if (country.income === 'lower-middle') baseMortality = 35;

        // Coverage impact
        const coverageImpact = (100 - coverage) * 0.5;

        return Math.round(baseMortality + coverageImpact);
    }

    calculateLivesSaved(country, currentCoverage, historicalCoverage) {
        const improvement = currentCoverage - historicalCoverage;
        const birthCohort = Math.round(country.population * 0.012);
        const mortalityRate = this.calculateMortality(country, currentCoverage) / 1000;

        return Math.round(birthCohort * (improvement / 100) * mortalityRate * 50); // 50 years
    }

    calculateMeaslesCases(country, coverage) {
        // Cases inversely related to coverage
        const susceptible = (100 - coverage) / 100;
        const birthCohort = Math.round(country.population * 0.015);

        return Math.round(birthCohort * susceptible * this.random(0.1, 0.4));
    }

    calculateMeaslesDeaths(country, coverage) {
        const cases = this.calculateMeaslesCases(country, coverage);
        const cfr = country.income === 'low' ? 0.05 : country.income === 'lower-middle' ? 0.02 : 0.005;

        return Math.round(cases * cfr);
    }

    getCervicalCancerRate(country, coverage) {
        // Higher coverage = lower cancer rate
        let baseRate = 25;

        if (country.income === 'high') baseRate = 8;
        else if (country.income === 'upper-middle') baseRate = 15;

        const coverageImpact = (100 - coverage) * 0.15;

        return Math.max(2, Math.round(baseRate + coverageImpact));
    }

    getCervicalCancerMortality(country, coverage) {
        return Math.round(this.getCervicalCancerRate(country, coverage) * 0.55);
    }

    calculateHPVLivesSaved(country, coverage) {
        const womenPopulation = country.population * 0.5;
        const targetAge = womenPopulation * 0.15; // 15% in target age
        const cancerRate = this.getCervicalCancerRate(country, 0) / 100000;

        return Math.round(targetAge * cancerRate * (coverage / 100) * 0.87); // 87% effectiveness
    }

    calculateAnnualDeaths(country, coverage) {
        const incidence = this.getCervicalCancerRate(country, coverage);
        const womenPopulation = country.population * 0.5;

        return Math.round((incidence / 100000) * womenPopulation * 0.55);
    }

    /**
     * Historical data helpers
     */
    getPolioFreeYear(country) {
        if (this.isPolioEndemic(country)) return null;

        // Americas: 1994, Western Pacific: 2000, Europe: 2002, Southeast Asia: 2014, Africa: 2020
        const regionYears = {
            'PAHO': 1994,
            'WPRO': 2000,
            'EURO': 2002,
            'SEARO': 2014,
            'AFRO': 2020,
            'EMRO': null
        };

        return regionYears[country.region] || 2020;
    }

    isPolioEndemic(country) {
        // Only Pakistan and Afghanistan remain endemic
        return ['PAK', 'AFG'].includes(country.iso3);
    }

    wasEndemicIn1950(country) {
        // Most countries were endemic in 1950
        return country.income !== 'high' || this.random(0, 100) > 70;
    }

    wasEndemicIn1960(country) {
        return this.wasEndemicIn1950(country) && country.income !== 'high';
    }

    wasEndemicIn1970(country) {
        return country.income === 'low' || (country.income === 'lower-middle' && this.random(0, 100) > 50);
    }

    getEradicationYear(country) {
        if (country.income === 'high') return this.random(1950, 1965);
        if (country.income === 'upper-middle') return this.random(1960, 1975);
        return this.random(1970, 1978);
    }

    getLastCaseYear(country) {
        return this.getEradicationYear(country) - this.random(1, 3);
    }

    getVaccinationIntensity(country) {
        if (country.income === 'high') return this.random(80, 100);
        if (country.income === 'upper-middle') return this.random(60, 85);
        if (country.income === 'lower-middle') return this.random(40, 70);
        return this.random(20, 55);
    }

    /**
     * Utility functions
     */
    random(min, max) {
        return Math.floor(Math.random() * (max - min + 1)) + min;
    }

    interpolate(start, end, factor) {
        return Math.round(start + (end - start) * factor);
    }
}

// Export factory function for easy use
export function generateVaccineData(vaccineType) {
    const generator = new VaccineDataGenerator(vaccineType);
    return generator.generateData();
}
