"""
Quick self-test — validates core parsing logic without external deps.
Run with: pytest tests/test_quick.py -v
"""

import tempfile
import textwrap
from pathlib import Path

from hld_generator.config import LANGUAGE_MAP, HLDConfig
from hld_generator.scanner import FileScanner
from hld_generator.parsers.base import EntityType
from hld_generator.parsers.regex_parser import RegexParser


def test_language_map():
    assert LANGUAGE_MAP[".py"] == "python"
    assert LANGUAGE_MAP[".ts"] == "typescript"
    assert LANGUAGE_MAP[".go"] == "go"
    assert LANGUAGE_MAP[".rs"] == "rust"


def test_config_defaults():
    cfg = HLDConfig()
    assert cfg.llm_model == "claude-sonnet-4-20250514"
    cfg2 = HLDConfig(llm_provider="openai")
    assert cfg2.llm_model == "gpt-4o"


def test_regex_parser_python():
    parser = RegexParser()
    with tempfile.NamedTemporaryFile(suffix=".py", mode="w", delete=False) as f:
        f.write(textwrap.dedent("""\
            # My module
            import os
            from pathlib import Path, PurePath
            from .utils import helper

            class MyService:
                def process(self, data):
                    pass

                def validate(self, input):
                    pass

            class MyRepo:
                def fetch(self):
                    pass

            def main():
                svc = MyService()

            @app.get("/api/users")
            def list_users():
                pass

            @app.post("/api/users")
            def create_user():
                pass
        """))
        f.flush()
        result = parser.parse_file(Path(f.name), "python")

    assert len(result.classes) == 2, f"Expected 2 classes, got {len(result.classes)}"
    assert result.classes[0].name == "MyService"
    assert result.classes[1].name == "MyRepo"

    funcs = [e for e in result.entities if e.entity_type in (EntityType.FUNCTION, EntityType.METHOD)]
    func_names = {f.name for f in funcs}
    assert "main" in func_names
    assert "process" in func_names
    assert "validate" in func_names

    assert len(result.imports) >= 3
    assert any("pathlib" in imp.module for imp in result.imports)
    assert any(imp.is_relative for imp in result.imports)

    endpoints = result.endpoints
    assert len(endpoints) == 2, f"Expected 2 endpoints, got {len(endpoints)}"


def test_regex_parser_javascript():
    parser = RegexParser()
    with tempfile.NamedTemporaryFile(suffix=".js", mode="w", delete=False) as f:
        f.write(textwrap.dedent("""\
            import React from 'react';
            import { useState, useEffect } from 'react';
            const axios = require('axios');

            class UserService {
                async getUsers() { }
            }

            function formatDate(d) { }

            const processData = async (input) => { };

            export default class UserExport {}

            app.get('/api/health', (req, res) => {});
            router.post('/api/login', handleLogin);
        """))
        f.flush()
        result = parser.parse_file(Path(f.name), "javascript")

    assert len(result.classes) >= 1
    assert result.classes[0].name == "UserService"
    assert len(result.imports) >= 2

    func_names = {e.name for e in result.entities if e.entity_type in (EntityType.FUNCTION, EntityType.METHOD)}
    assert "formatDate" in func_names

    assert len(result.endpoints) >= 2
    assert len(result.exports) >= 1


def test_regex_parser_go():
    parser = RegexParser()
    with tempfile.NamedTemporaryFile(suffix=".go", mode="w", delete=False) as f:
        f.write(textwrap.dedent("""\
            package main

            import "fmt"
            import "net/http"

            type Server struct {
                port int
            }

            type Handler interface {
                Handle(r *Request)
            }

            func (s *Server) Start() { }

            func main() {
                fmt.Println("hello")
            }
        """))
        f.flush()
        result = parser.parse_file(Path(f.name), "go")

    class_names = {e.name for e in result.entities if e.entity_type == EntityType.CLASS}
    assert "Server" in class_names

    iface_names = {e.name for e in result.entities if e.entity_type == EntityType.INTERFACE}
    assert "Handler" in iface_names

    func_names = {e.name for e in result.entities if e.entity_type in (EntityType.FUNCTION, EntityType.METHOD)}
    assert "main" in func_names
    assert "Start" in func_names


def test_regex_parser_java():
    parser = RegexParser()
    with tempfile.NamedTemporaryFile(suffix=".java", mode="w", delete=False) as f:
        f.write(textwrap.dedent("""\
            package com.example;

            import java.util.List;
            import java.util.Optional;

            public class UserController {
                public List<User> getUsers() { return null; }
                private void validate(User u) { }

                @GetMapping("/api/users")
                public List<User> listAll() { return null; }
            }

            interface UserRepository {
                Optional<User> findById(Long id);
            }
        """))
        f.flush()
        result = parser.parse_file(Path(f.name), "java")

    assert len(result.classes) >= 1
    func_names = {e.name for e in result.entities if e.entity_type in (EntityType.FUNCTION, EntityType.METHOD)}
    assert "getUsers" in func_names
    assert len(result.imports) >= 2
    assert len(result.endpoints) >= 1


def test_scanner():
    with tempfile.TemporaryDirectory() as tmpdir:
        root = Path(tmpdir)
        (root / "src").mkdir()
        (root / "src" / "main.py").write_text("def main(): pass")
        (root / "src" / "utils.py").write_text("def helper(): pass")
        (root / "node_modules").mkdir()
        (root / "node_modules" / "pkg.js").write_text("junk")
        (root / "test_foo.py").write_text("def test_x(): pass")

        config = HLDConfig(target=root)
        scanner = FileScanner(config)
        files = scanner.scan()

        paths = {f.relative_path for f in files}
        assert "src/main.py" in paths
        assert "src/utils.py" in paths
        # node_modules should be skipped
        assert not any("node_modules" in p for p in paths)
        # test files skipped by default
        assert not any("test_foo" in p for p in paths)

        # With tests included
        config2 = HLDConfig(target=root, include_tests=True)
        files2 = FileScanner(config2).scan()
        paths2 = {f.relative_path for f in files2}
        assert "test_foo.py" in paths2
