<?php

namespace App\Http\Controllers\MME;

use App\Exports\MME_Export\STI\STIExport;
use App\Http\Controllers\Controller;
use ReflectionClass;

class DocumentationDictionaryExportController extends Controller
{
    public function sti(string $sex)
    {
        abort_unless(auth()->user() && auth()->user()->type == 1, 403);

        $sex = ucfirst(strtolower($sex));
        abort_unless(in_array($sex, ['Male', 'Female'], true), 404);

        $rows = $this->stiDictionaryRows($sex);
        $filename = 'STI_' . $sex . '_Data_Dictionary_' . date('d-m-Y') . '.csv';

        return response()->streamDownload(function () use ($rows) {
            $handle = fopen('php://output', 'w');
            fwrite($handle, "\xEF\xBB\xBF");
            fputcsv($handle, [
                'No.',
                'Program',
                'Dataset',
                'Export Column',
                'Database / Source Field',
                'HTML Field Name',
                'Field Group',
                'Data Format',
                'Data Interpretation',
                'Reference Source',
            ]);

            foreach ($rows as $row) {
                fputcsv($handle, $row);
            }

            fclose($handle);
        }, $filename, [
            'Content-Type' => 'text/csv; charset=UTF-8',
        ]);
    }

    private function stiDictionaryRows(string $sex): array
    {
        $columns = $this->stiExportColumns($sex);
        $htmlMap = $this->stiHtmlFieldMap($sex);
        $rows = [];

        foreach ($columns as $index => $column) {
            $exportColumn = $column[0] ?? '';
            $sourceField = $column[1] ?? '';
            $group = $this->stiFieldGroup($sex, $sourceField, $exportColumn);

            $rows[] = [
                $index + 1,
                'STI Program',
                'STI ' . $sex,
                $exportColumn,
                $sourceField,
                $htmlMap[$sourceField] ?? '',
                $group,
                $this->stiDataFormat($sex, $sourceField, $exportColumn, $group),
                $this->stiInterpretation($sex, $sourceField, $exportColumn, $group),
                $this->stiReferenceSource($sourceField, $group),
            ];
        }

        return $rows;
    }

    private function stiExportColumns(string $sex): array
    {
        $export = new STIExport(collect(), $sex);
        $reflection = new ReflectionClass($export);
        $method = $reflection->getMethod('exportColumns');

        return $method->invoke($export);
    }

    private function stiHtmlFieldMap(string $sex): array
    {
        $file = public_path('js/STI/stiform-page.js');
        if (!is_file($file)) {
            return [];
        }

        $content = file_get_contents($file);
        $variable = $sex === 'Male' ? 'sti_male_collect' : 'sti_female_collect';
        if (!preg_match('/const\s+' . preg_quote($variable, '/') . '\s*=\s*\[(.*?)\]\s*/s', $content, $match)) {
            return [];
        }

        preg_match_all("/'([^']*)'/", $match[1], $tokens);
        $values = $tokens[1] ?? [];
        $map = [];

        for ($i = 0; $i + 1 < count($values); $i += 2) {
            $map[$values[$i]] = $values[$i + 1];
        }

        return $map;
    }

    private function stiFieldGroup(string $sex, string $field, string $column): string
    {
        $field = trim($field);
        $identity = ['__database', 'Clinic Code', 'CID', 'FuchiaID', 'Gender', 'Reg year', 'Register Agey', 'Register Agem', 'Current Agey', 'Current Agem', 'Visit_date'];
        $history = ['tbl_demog_first_visit', 'first_visit', 'last_vis_within', 'about_clinic', 'Reason for Visit', 'rea_for_visit', 'Main Risk', 'Sub Risk', 'demo_remarks', 'visit_type', 'visit_time', 'followup_visit', 'episode'];
        $diagnosis = ['presumptive_diag', 'pri_syphillis', 'sec_syphillis', 'chancroid', 'gen_herpes', 'gen_scabies', 'gud_other', 'other(please specify)', 'Gonorhoea', 'non_gono_urethritis', 'non_gono_procti', 'non_gono_cervities', 'trichomonas', 'genital_candidiosis', 'beterial_vaginosis', 'congenial_syphillis', 'latent_syphillis', 'latent_syphillis_preg', 'molluscum_contag', 'bubos', 'othstd_genital_warts', 'ostd_other', 'other_STD', 'other_plz_specify'];
        $treatment = ['tre_azythro', 'acyclovir', 'clotrimazole', 'clotrimazole_vaginal_tab', 'tre_podophyllin', 'tre_cefixim', 'tre_ciprofloxacin', 'tre_tinidazole', 'tre_fluconazole', 'tre_doxycycline', 'tre_ceftriaxone', 'tre_benz_pen', 'no_treat', 'no_treatment', 'tre_Other', 'al_Penicillin', 'al_sulfa', 'part_treat', 'condom_giv', 'counsel_disclosure', 'counsellor_sti_sign_symptom', 'counsel_vaginal', 'treatment_side_effect', 'tre_remarks', 'followup', 'clinician_name', 'clinician'];
        $prior = ['previous_sti', 'previous_what', 'previous_when', 'prior_sti', 'prior_what', 'prior_when', 'prior_other_comment', 'prev_STI'];
        $femaleRisk = ['patient_genital_ulcer', 'patient_compl_low_abd', 'new_pat_past_3mont', 'part_compl_gential_sym', 'sworker', 'rg_score', 'risk', 'abn_yellow_disc', 'low_abd_pain', 'if_only_abnormal_abundant', 'unp_sex_new_clients', 'dysuria_risk_ass', 'partner_ulcer', 'high_rg_score', 'high_risk', 'risk_cal_remark', 'pain_dur_sexual'];

        if (in_array($field, $identity, true)) {
            return 'Patient identity and visit';
        }
        if (in_array($field, $history, true)) {
            return 'Visit history and risk';
        }
        if (in_array($field, $prior, true)) {
            return 'Previous or prior STI';
        }
        if ($sex === 'Female' && in_array($field, $femaleRisk, true)) {
            return 'Female risk assessment';
        }
        if (in_array($field, $diagnosis, true)) {
            return 'STI diagnosis';
        }
        if (in_array($field, $treatment, true)) {
            return 'Treatment, counselling, and follow-up';
        }

        if ($sex === 'Male' && in_array($field, $this->malePhysicalFields(), true)) {
            return 'Male physical examination';
        }
        if ($sex === 'Female' && in_array($field, $this->femalePhysicalFields(), true)) {
            return 'Female physical examination';
        }

        return $sex . ' symptoms';
    }

    private function stiDataFormat(string $sex, string $field, string $column, string $group): string
    {
        if ($field === 'CID') {
            return 'Number; length 10, 11, or 12.';
        }
        if ($field === '__database') {
            return 'Database/connection name text.';
        }
        if (in_array($field, ['FuchiaID', 'clinic', 'Clinic Code'], true)) {
            return 'Text/list value.';
        }
        if ($field === 'Gender') {
            return 'Male or Female.';
        }
        if ($field === 'Reg year') {
            return 'YYYY.';
        }
        if (in_array($field, ['Register Agey', 'Current Agey'], true)) {
            return 'Number.';
        }
        if (in_array($field, ['Register Agem', 'Current Agem'], true)) {
            return 'Number from 1 to 11.';
        }
        if ($this->containsAny($field, ['date', 'when']) || $this->containsAny($column, ['date', 'when'])) {
            return 'Date in DD-MM-YYYY export format, or blank when not applicable.';
        }
        if ($field === 'last_vis_within') {
            return '1=Within 3 months, 2=>3 months ago, 9=Missing.';
        }
        if ($field === 'about_clinic') {
            return '1=From HE Team, 2=From Partner, 3=From Others, 4=Missing.';
        }
        if (in_array($field, ['Reason for Visit', 'rea_for_visit'], true)) {
            return '1=Symptomatic, 2=Screening/non-symptomatic, 3=Partner STI, 9=Missing.';
        }
        if (in_array($field, ['Main Risk', 'Sub Risk'], true)) {
            return 'Coded/list value; see Code Book sheet.';
        }
        if (in_array($field, ['tbl_demog_first_visit', 'first_visit'], true)) {
            return '1=Yes, 2=No, 9=Missing.';
        }
        if (in_array($field, ['pain', 'pain_full_less', 'gential_ulcer_pain'], true)) {
            return '1=Painful, 2=Painless, 9=Missing.';
        }
        if (in_array($field, ['ulcer', 'sing_multi', 'gent_ulcer_sm'], true)) {
            return '1=Single, 2=Multiple, 9=Missing.';
        }
        if ($field === 'colour') {
            return '1=Clear, 2=White, 3=Yellow, 4=Bloody, 5=Other, 9=Missing.';
        }
        if ($field === 'amount') {
            return 'Coded amount value; commonly 1=Abundant, 2/0=Normal in current/legacy data.';
        }
        if (in_array($field, ['rg_score', 'high_rg_score'], true)) {
            return 'Numeric risk score calculated from current JavaScript answers.';
        }
        if (in_array($field, ['risk', 'high_risk'], true)) {
            return 'Low Risk or High Risk, calculated by current JavaScript.';
        }
        if ($this->containsAny($field, ['hl', 'howlong', 'size', 'description', 'remark', 'comment', 'reason', 'what', 'clinician'])) {
            return 'Free text, number, or short staff text according to the field label.';
        }
        if ($group === 'Treatment, counselling, and follow-up') {
            return 'Checkbox/service flag or selected value; commonly 1=selected/yes and 0/2=not selected/no. Text fields remain free text.';
        }
        if ($group === 'STI diagnosis') {
            return 'Diagnosis flag; commonly 1=Yes/selected, 2=No, 9=Missing. Other diagnosis fields may be free text.';
        }

        return 'Coded select value; commonly 1=Yes, 2=No, 9=Missing, with blank allowed when not applicable.';
    }

    private function stiInterpretation(string $sex, string $field, string $column, string $group): string
    {
        if ($group === 'Patient identity and visit') {
            return 'Links the STI variable to the patient, clinic, sex, age, and visit date used for reporting.';
        }
        if ($group === 'Visit history and risk') {
            return 'Explains visit type, source/referral context, reason for attendance, and risk category.';
        }
        if ($group === 'Previous or prior STI') {
            return 'Records previous STI history and related what/when details used for clinical context.';
        }
        if ($group === 'Female risk assessment') {
            return 'Female risk-score item or calculated result from the current JavaScript workflow.';
        }
        if ($group === 'STI diagnosis') {
            return 'Diagnosis or syndrome flag used in STI export and reporting.';
        }
        if ($group === 'Treatment, counselling, and follow-up') {
            return 'Treatment, counselling, allergy, partner treatment, condom, side-effect, follow-up, or clinician accountability field.';
        }
        if ($group === 'Male physical examination' || $group === 'Female physical examination') {
            return 'Clinician-observed examination finding, size/location/detail, or drawing description.';
        }

        return $sex . ' symptom, complaint, duration, or related clinical detail used to guide diagnosis and treatment.';
    }

    private function stiReferenceSource(string $field, string $group): string
    {
        if (in_array($field, ['CID', 'FuchiaID', 'Gender', 'Reg year', 'Register Agey', 'Register Agem', 'Current Agey', 'Current Agem', 'Visit_date', 'last_vis_within', 'about_clinic', 'Main Risk', 'Sub Risk'], true)) {
            return 'Excel Data_Dictionary_EMR_15May2025.xlsx plus current STI export.';
        }

        return 'Current STI Blade, JavaScript field map, controller/model, and StiExport.';
    }

    private function containsAny(string $value, array $needles): bool
    {
        $value = strtolower($value);
        foreach ($needles as $needle) {
            if (strpos($value, strtolower($needle)) !== false) {
                return true;
            }
        }

        return false;
    }

    private function malePhysicalFields(): array
    {
        return [
            'physical_exam', 'physical_exam_no_reason', 'urinated_wit_1h', 'discharge', 'discharge_milk',
            'colour', 'erythema', 'blisters', 'gen_ulcer', 'esti_size', 'sing_multi', 'pain_full_less',
            'herpes_suspect', 'inguinal_bubo', 'fluctant', 'tendr_ntender', 'oth_leg_inf',
            'phy_genital_wart', 'crab_lice', 'scabies', 'gscrotal_swelling', 'estimated_siz',
            'unilateal_bilateral', 'gtender_ntender', 'erythem', 'des_size', 'drawing_description',
        ];
    }

    private function femalePhysicalFields(): array
    {
        return [
            'phy_exam_done', 'physical_exam_no_reason', 'washed_inside', 'vulvar_erythema', 'vulvar_odema',
            'vaginal_discharge', 'vag_dis_amount', 'homogeneous', 'homogeneous_col', 'smell_without_KOH',
            'vaginal_wall_injury', 'endocervical_mucopus', 'endocervical_colour', 'cerv_motion_tenderness',
            'adnexal_tenderness', 'adnexal_enlargement', 'genital_blisters', 'genital_blisters_Location',
            'gential_ulcer', 'gential_ulcerl', 'gent_ulcer_sm', 'gential_ulcer_pain', 'susp_herpes',
            'inguinal_bubo', 'fluctuant', 'fluctuant_tender', 'oth_leg_infection', 'genital_wart',
            'crab_lice', 'scablices', 'KOH_smell_test', 'pH_vagina', 'des_size', 'drawing_description',
        ];
    }
}
