#!/usr/bin/env python3
"""
Download D2 and D3 forms from internship.cse.hcmut.edu.vn

Saves:
  - ./forms/d2/  — D2 form files
  - ./forms/d3/  — D3 form files
  - ./forms/company_info.json — company metadata
"""

import json
import os
import re
import sys
import time
from pathlib import Path

import requests

BASE_URL = "https://internship.cse.hcmut.edu.vn"
LIST_ENDPOINT = "/home/company/all"
DETAIL_ENDPOINT = "/home/company/id/"

REQUEST_TIMEOUT = 30
USER_AGENT = (
    "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 "
    "(KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"
)

D2_DIR = Path("./forms/d2")
D3_DIR = Path("./forms/d3")
INFO_FILE = Path("./forms/company_info.json")


def fetch_company_list(session: requests.Session) -> list[dict]:
    url = f"{BASE_URL}{LIST_ENDPOINT}"
    params = {"t": int(time.time() * 1000), "condition": ""}
    resp = session.get(url, params=params, timeout=REQUEST_TIMEOUT)
    resp.raise_for_status()
    return resp.json().get("items", [])


def fetch_company_detail(session: requests.Session, company_id: str) -> dict | None:
    url = f"{BASE_URL}{DETAIL_ENDPOINT}{company_id}"
    resp = session.get(url, timeout=REQUEST_TIMEOUT)
    resp.raise_for_status()
    data = resp.json()
    if data.get("error"):
        return None
    return data.get("item")


def classify_form(filename: str) -> str:
    match = re.search(r"_D([23])_", filename, re.IGNORECASE)
    if match:
        return f"D{match.group(1)}"
    if re.search(r"\bD2\b", filename, re.IGNORECASE):
        return "D2"
    if re.search(r"\bD3\b", filename, re.IGNORECASE):
        return "D3"
    return "other"


def download_file(session: requests.Session, path: str, dest: Path) -> bool:
    """Download a file from the server. Returns True on success."""
    if not path:
        return False
    url = f"{BASE_URL}{path}" if path.startswith("/") else path
    try:
        resp = session.get(url, timeout=REQUEST_TIMEOUT)
        resp.raise_for_status()
        dest.parent.mkdir(parents=True, exist_ok=True)
        dest.write_bytes(resp.content)
        return True
    except Exception as e:
        print(f"    Failed: {e}", file=sys.stderr)
        return False


def main():
    D2_DIR.mkdir(parents=True, exist_ok=True)
    D3_DIR.mkdir(parents=True, exist_ok=True)

    session = requests.Session()
    session.headers.update({"User-Agent": USER_AGENT})

    print("Fetching company list...", file=sys.stderr)
    companies = fetch_company_list(session)
    print(f"Found {len(companies)} companies", file=sys.stderr)

    company_info = []
    d2_count = 0
    d3_count = 0

    for i, company in enumerate(companies):
        company_id = company.get("_id", "?")
        shortname = company.get("shortname", "?")
        print(f"  [{i+1}/{len(companies)}] {shortname}", file=sys.stderr)

        detail = fetch_company_detail(session, company_id)
        if not detail:
            continue

        # Collect forms
        d2_forms = []
        d3_forms = []
        for f in detail.get("internshipFiles", []):
            name = f.get("name", "")
            path = f.get("path", "")
            form_type = classify_form(name)
            if form_type == "D2":
                d2_forms.append({"name": name, "path": path})
            elif form_type == "D3":
                d3_forms.append({"name": name, "path": path})

        # Also check main internshipFile
        main_file = detail.get("internshipFile", "")
        if main_file:
            main_name = main_file.rsplit("/", 1)[-1]
            form_type = classify_form(main_name)
            if form_type == "D2":
                d2_forms.append({"name": main_name, "path": main_file})
            elif form_type == "D3":
                d3_forms.append({"name": main_name, "path": main_file})

        # Download D2 forms
        for form in d2_forms:
            # Use company shortname + form name for safe filename
            safe_company = re.sub(r'[^\w\s-]', '', shortname).strip().replace(' ', '_')
            safe_name = re.sub(r'[^\w\s-]', '', form["name"]).strip().replace(' ', '_')
            filename = f"{safe_company}_{safe_name}"
            dest = D2_DIR / filename
            if download_file(session, form["path"], dest):
                d2_count += 1
                print(f"    D2 -> {dest}", file=sys.stderr)

        # Download D3 forms
        for form in d3_forms:
            safe_company = re.sub(r'[^\w\s-]', '', shortname).strip().replace(' ', '_')
            safe_name = re.sub(r'[^\w\s-]', '', form["name"]).strip().replace(' ', '_')
            filename = f"{safe_company}_{safe_name}"
            dest = D3_DIR / filename
            if download_file(session, form["path"], dest):
                d3_count += 1
                print(f"    D3 -> {dest}", file=sys.stderr)

        # Save company info
        max_accepted = detail.get("maxAcceptedStudent", 0)
        student_accepted = detail.get("studentAccepted", 0)
        accepted_intern = detail.get("acceptedIntern", False)
        active = detail.get("active", False)

        if not active:
            acceptance = "inactive"
        elif not accepted_intern:
            acceptance = "not_accepting"
        elif student_accepted >= max_accepted:
            acceptance = "full"
        else:
            acceptance = "accepting"

        company_info.append({
            "id": company_id,
            "shortname": detail.get("shortname", shortname),
            "fullname": detail.get("fullname", ""),
            "location": detail.get("address", ""),
            "max_slot": max_accepted,
            "student_accepted": student_accepted,
            "acceptance": acceptance,
            "d2_forms": [f["name"] for f in d2_forms],
            "d3_forms": [f["name"] for f in d3_forms],
        })

    # Save company info JSON
    INFO_FILE.parent.mkdir(parents=True, exist_ok=True)
    with open(INFO_FILE, "w", encoding="utf-8") as f:
        json.dump(company_info, f, ensure_ascii=False, indent=2)

    print(f"\nDone!", file=sys.stderr)
    print(f"  D2 forms: {d2_count} files -> {D2_DIR}/", file=sys.stderr)
    print(f"  D3 forms: {d3_count} files -> {D3_DIR}/", file=sys.stderr)
    print(f"  Company info: {INFO_FILE}", file=sys.stderr)


if __name__ == "__main__":
    main()
