use std::path::Path;

/// PostgreSQL detector
/// Detects: PostgreSQL usage via dependencies, migrations, connection strings
use super::helpers;
use crate::error::DetectionResult;
use crate::models::{Detection, Evidence, Technology};

pub struct PostgresDetector;

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

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

    fn detect(&self, project_path: &Path) -> DetectionResult<Option<Detection>> {
        let mut confidence = 0.0;
        let mut evidence = Vec::new();

        // Check for database/migrations directory
        if helpers::file_exists(project_path, "migrations")? {
            evidence.push(Evidence::FileExists {
                path: project_path.join("migrations"),
                reason: "Database migrations directory suggests SQL database".into(),
            });
            confidence += 0.3;
        }

        if helpers::file_exists(project_path, "database")? {
            evidence.push(Evidence::FileExists {
                path: project_path.join("database"),
                reason: "Database directory".into(),
            });
            confidence += 0.2;
        }

        // Check for postgres dependency in various package managers
        if let Ok(content) = helpers::read_file(project_path, "package.json") {
            if content.contains("\"pg\"") || content.contains("\"postgres\"") {
                evidence.push(Evidence::Dependency {
                    name: "pg".into(),
                    version: None,
                    reason: "PostgreSQL client for Node.js".into(),
                });
                confidence += 0.4;
            }
        }

        if let Ok(content) = helpers::read_file(project_path, "requirements.txt") {
            if content.contains("psycopg") || content.contains("sqlalchemy") {
                evidence.push(Evidence::Dependency {
                    name: "psycopg2".into(),
                    version: None,
                    reason: "PostgreSQL adapter for Python".into(),
                });
                confidence += 0.4;
            }
        }

        if let Ok(content) = helpers::read_file(project_path, "Cargo.toml") {
            if content.contains("tokio-postgres") || content.contains("sqlx") {
                evidence.push(Evidence::Dependency {
                    name: "tokio-postgres".into(),
                    version: None,
                    reason: "PostgreSQL driver for Rust".into(),
                });
                confidence += 0.5;
            }
        }

        // Search for connection strings in code
        if let Ok(pattern) = regex::Regex::new(r"postgres://|postgresql://") {
            if let Ok(results) =
                helpers::grep_in_project(project_path, &pattern, &["js", "ts", "py", "rs"])
            {
                if !results.is_empty() {
                    evidence.push(Evidence::FileContent {
                        path: results[0].path.clone(),
                        pattern: "postgres://".into(),
                        line: results[0].line_num,
                        reason: "PostgreSQL connection string found".into(),
                    });
                    confidence += 0.3;
                }
            }
        }

        if confidence > 0.0 {
            let mut detection = Detection::new(Technology::Postgres);
            for ev in evidence {
                detection = detection.add_evidence(ev);
            }
            detection.calculate_confidence();
            Ok(Some(detection))
        } else {
            Ok(None)
        }
    }
}

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

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

    fn priority(&self) -> u8 {
        50 // Medium priority
    }
}
