use super::{StageResult, StageError};
use super::icr::{ICR, SegmentType};
use crate::types::Script;

/// Stage 5: Target Script Generation
/// Converts ICR to target script (Arabic or Latin)
pub struct ScriptGenerator;

impl ScriptGenerator {
    pub fn new() -> Self {
        ScriptGenerator
    }

    /// Generate target script from ICR
    pub fn generate(&self, icr: &ICR, target_script: Script) -> StageResult<String> {
        match target_script {
            Script::Arabic => self.icr_to_arabic(icr),
            Script::Latin => self.icr_to_latin(icr),
            Script::Mixed => Err(StageError::ScriptGeneration(
                "Cannot generate mixed script directly".to_string()
            )),
            Script::Unknown => Err(StageError::ScriptGeneration(
                "Cannot generate unknown script".to_string()
            )),
        }
    }

    /// Convert ICR to Arabic script
    fn icr_to_arabic(&self, icr: &ICR) -> StageResult<String> {
        let mut result = String::new();
        let mut prev_was_vowel = false;

        for segment in &icr.segments {
            let arabic_char = self.canonical_to_arabic(&segment.canonical, segment.segment_type);

            // Handle vowel placement in Arabic
            if matches!(segment.segment_type, SegmentType::Vowel) {
                // In Arabic, we might want to use diacritics or long vowels
                if !prev_was_vowel {
                    result.push_str(arabic_char);
                }
                prev_was_vowel = true;
            } else {
                result.push_str(arabic_char);
                prev_was_vowel = false;
            }
        }

        if result.is_empty() {
            return Err(StageError::ScriptGeneration(
                "Generated Arabic text is empty".to_string()
            ));
        }

        Ok(result)
    }

    /// Convert ICR to Latin script
    fn icr_to_latin(&self, icr: &ICR) -> StageResult<String> {
        let mut result = String::new();

        for segment in &icr.segments {
            let latin_char = self.canonical_to_latin(&segment.canonical, segment.segment_type);
            result.push_str(latin_char);
        }

        if result.is_empty() {
            return Err(StageError::ScriptGeneration(
                "Generated Latin text is empty".to_string()
            ));
        }

        Ok(result)
    }

    /// Map canonical form to Arabic character
    fn canonical_to_arabic(&self, canonical: &str, _segment_type: SegmentType) -> &'static str {
        match canonical {
            "A" => "ا",
            "B" => "ب",
            "T" => "ت",
            "Ṯ" => "ث",
            "J" => "ج",
            "Ḥ" => "ح",
            "X" => "خ",
            "D" => "د",
            "Ḏ" => "ذ",
            "R" => "ر",
            "Z" => "ز",
            "S" => "س",
            "Š" => "ش",
            "Ṣ" => "ص",
            "Ḍ" => "ض",
            "Ṭ" => "ط",
            "Ẓ" => "ظ",
            "ε" => "ع",
            "Ġ" => "غ",
            "F" => "ف",
            "Q" => "ق",
            "K" => "ك",
            "L" => "ل",
            "M" => "م",
            "N" => "ن",
            "H" => "ه",
            "W" => "و",
            "Y" => "ي",
            "I" => "ي",
            "U" => "و",
            " " => " ",
            _ => "",
        }
    }

    /// Map canonical form to Latin character
    fn canonical_to_latin(&self, canonical: &str, _segment_type: SegmentType) -> &'static str {
        match canonical {
            "A" => "a",
            "B" => "b",
            "T" => "t",
            "Ṯ" => "th",
            "J" => "j",
            "Ḥ" => "7", // Using common Darija notation
            "X" => "kh",
            "D" => "d",
            "Ḏ" => "dh",
            "R" => "r",
            "Z" => "z",
            "S" => "s",
            "Š" => "sh",
            "Ṣ" => "s", // Simplified
            "Ḍ" => "d", // Simplified
            "Ṭ" => "t", // Simplified
            "Ẓ" => "z", // Simplified
            "ε" => "3", // Using common Darija notation
            "Ġ" => "gh",
            "F" => "f",
            "Q" => "q",
            "K" => "k",
            "L" => "l",
            "M" => "m",
            "N" => "n",
            "H" => "h",
            "W" => "w",
            "Y" => "y",
            "I" => "i",
            "U" => "u",
            " " => " ",
            _ => "",
        }
    }
}

impl Default for ScriptGenerator {
    fn default() -> Self {
        Self::new()
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::types::Dialect;
    use crate::stages::icr::{ICRSegment, ICRMetadata};

    #[test]
    fn test_icr_to_arabic() {
        let generator = ScriptGenerator::new();

        // Create a simple ICR
        let icr = ICR {
            segments: vec![
                ICRSegment {
                    canonical: "S".to_string(),
                    original: "s".to_string(),
                    segment_type: SegmentType::Consonant,
                    confidence: 1.0,
                },
                ICRSegment {
                    canonical: "L".to_string(),
                    original: "l".to_string(),
                    segment_type: SegmentType::Consonant,
                    confidence: 1.0,
                },
                ICRSegment {
                    canonical: "A".to_string(),
                    original: "a".to_string(),
                    segment_type: SegmentType::Vowel,
                    confidence: 1.0,
                },
                ICRSegment {
                    canonical: "M".to_string(),
                    original: "m".to_string(),
                    segment_type: SegmentType::Consonant,
                    confidence: 1.0,
                },
            ],
            dialect: Dialect::Moroccan,
            metadata: ICRMetadata {
                source_script: Script::Latin,
                total_segments: 4,
                confidence_avg: 1.0,
            },
        };

        let result = generator.generate(&icr, Script::Arabic).unwrap();
        assert_eq!(result, "سلام");
    }

    #[test]
    fn test_icr_to_latin() {
        let generator = ScriptGenerator::new();

        // Create a simple ICR
        let icr = ICR {
            segments: vec![
                ICRSegment {
                    canonical: "S".to_string(),
                    original: "س".to_string(),
                    segment_type: SegmentType::Consonant,
                    confidence: 1.0,
                },
                ICRSegment {
                    canonical: "L".to_string(),
                    original: "ل".to_string(),
                    segment_type: SegmentType::Consonant,
                    confidence: 1.0,
                },
                ICRSegment {
                    canonical: "A".to_string(),
                    original: "ا".to_string(),
                    segment_type: SegmentType::Vowel,
                    confidence: 1.0,
                },
                ICRSegment {
                    canonical: "M".to_string(),
                    original: "م".to_string(),
                    segment_type: SegmentType::Consonant,
                    confidence: 1.0,
                },
            ],
            dialect: Dialect::Moroccan,
            metadata: ICRMetadata {
                source_script: Script::Arabic,
                total_segments: 4,
                confidence_avg: 1.0,
            },
        };

        let result = generator.generate(&icr, Script::Latin).unwrap();
        assert_eq!(result, "slam");
    }

    #[test]
    fn test_special_chars_to_latin() {
        let generator = ScriptGenerator::new();

        let icr = ICR {
            segments: vec![
                ICRSegment {
                    canonical: "ε".to_string(),
                    original: "ع".to_string(),
                    segment_type: SegmentType::Consonant,
                    confidence: 1.0,
                },
                ICRSegment {
                    canonical: "L".to_string(),
                    original: "ل".to_string(),
                    segment_type: SegmentType::Consonant,
                    confidence: 1.0,
                },
                ICRSegment {
                    canonical: "A".to_string(),
                    original: "ا".to_string(),
                    segment_type: SegmentType::Vowel,
                    confidence: 1.0,
                },
            ],
            dialect: Dialect::Moroccan,
            metadata: ICRMetadata {
                source_script: Script::Arabic,
                total_segments: 3,
                confidence_avg: 1.0,
            },
        };

        let result = generator.generate(&icr, Script::Latin).unwrap();
        assert_eq!(result, "3la"); // 'ayn represented as 3
    }
}
