use std::path::Path;

/// Python project detector
/// Detects: Python, pip/poetry/pipenv/uv, frameworks (Django, FastAPI, etc.)
use super::helpers;
use crate::error::DetectionResult;
use crate::models::{Detection, Evidence, Technology};

pub struct PythonDetector;

impl Default for PythonDetector {
    fn default() -> Self {
        Self
    }
}

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

    fn detect_requirements(&self, project_path: &Path) -> DetectionResult<Option<Detection>> {
        // Check for requirements.txt, setup.py, pyproject.toml, Pipfile, poetry.lock,
        // etc.

        let mut detection = None;

        // Primary indicators (high confidence)
        if helpers::file_exists(project_path, "requirements.txt")? {
            let mut det = Detection::new(Technology::Python);
            det = det.add_evidence(Evidence::FileExists {
                path: project_path.join("requirements.txt"),
                reason: "requirements.txt is pip dependency file".into(),
            });
            detection = Some(det);
        }

        if helpers::file_exists(project_path, "pyproject.toml")? {
            if detection.is_none() {
                let mut det = Detection::new(Technology::Python);
                det = det.add_evidence(Evidence::FileExists {
                    path: project_path.join("pyproject.toml"),
                    reason: "pyproject.toml is Python project config".into(),
                });
                detection = Some(det);
            } else if let Some(ref mut det) = detection {
                *det = det.clone().add_evidence(Evidence::FileExists {
                    path: project_path.join("pyproject.toml"),
                    reason: "pyproject.toml is Python project config".into(),
                });
            }
        }

        if helpers::file_exists(project_path, "setup.py")? {
            if detection.is_none() {
                let mut det = Detection::new(Technology::Python);
                det = det.add_evidence(Evidence::FileExists {
                    path: project_path.join("setup.py"),
                    reason: "setup.py is Python packaging file".into(),
                });
                detection = Some(det);
            } else if let Some(ref mut det) = detection {
                *det = det.clone().add_evidence(Evidence::FileExists {
                    path: project_path.join("setup.py"),
                    reason: "setup.py is Python packaging file".into(),
                });
            }
        }

        // Package manager files
        if helpers::file_exists(project_path, "Pipfile")? {
            if let Some(ref mut det) = detection {
                *det = det.clone().add_evidence(Evidence::FileExists {
                    path: project_path.join("Pipfile"),
                    reason: "Pipfile indicates pipenv".into(),
                });
            }
        }

        if helpers::file_exists(project_path, "poetry.lock")? {
            if let Some(ref mut det) = detection {
                *det = det.clone().add_evidence(Evidence::FileExists {
                    path: project_path.join("poetry.lock"),
                    reason: "poetry.lock indicates poetry".into(),
                });
            }
        }

        if helpers::file_exists(project_path, "uv.lock")? {
            if let Some(ref mut det) = detection {
                *det = det.clone().add_evidence(Evidence::FileExists {
                    path: project_path.join("uv.lock"),
                    reason: "uv.lock indicates uv package manager".into(),
                });
            }
        }

        // Framework detection
        if let Some(ref mut det) = detection {
            self.detect_frameworks(project_path, det)?;
            det.calculate_confidence();
        }

        Ok(detection)
    }

    fn detect_frameworks(
        &self,
        project_path: &Path,
        detection: &mut Detection,
    ) -> DetectionResult<()> {
        let frameworks = [
            ("django", "Web framework"),
            ("fastapi", "Async web framework"),
            ("flask", "Lightweight web framework"),
            ("requests", "HTTP library"),
            ("sqlalchemy", "ORM"),
        ];

        // Check in requirements.txt
        if let Ok(content) = helpers::read_file(project_path, "requirements.txt") {
            for (name, description) in &frameworks {
                if content.contains(name) {
                    *detection = detection.clone().add_evidence(Evidence::Dependency {
                        name: name.to_string(),
                        version: None,
                        reason: description.to_string(),
                    });
                }
            }
        }

        Ok(())
    }
}

impl super::Detector for PythonDetector {
    fn name(&self) -> &str {
        "python"
    }

    fn detect(&self, project_path: &Path) -> DetectionResult<Option<Detection>> {
        self.detect_requirements(project_path)
    }

    fn priority(&self) -> u8 {
        80 // High priority
    }
}

#[cfg(test)]
mod tests {
    use tempfile::TempDir;

    use super::*;
    use crate::detectors::Detector;

    #[test]
    fn test_detect_python_with_requirements() -> anyhow::Result<()> {
        let temp_dir = TempDir::new()?;
        std::fs::write(
            temp_dir.path().join("requirements.txt"),
            "flask==2.0.0\nrequests==2.26.0\n",
        )?;

        let detector = PythonDetector::new();
        let result = detector.detect(temp_dir.path())?;

        assert!(result.is_some());
        let detection = result.unwrap();
        assert_eq!(detection.technology, Technology::Python);
        assert!(detection.confidence > 0.0);

        Ok(())
    }
}
