import json
from pathlib import Path
from typing import Any

from app.config import settings
from app.services.repository import get_repository
from app.services.store import JsonStore


class D2LService:
    def __init__(self) -> None:
        self.store = JsonStore()
        self.repo = get_repository()

    def _snapshot_path(self) -> Path:
        candidate_dirs = [
            Path(settings.d2l_scraper_workdir),
            Path('/home/fizzlepoof/.openclaw/workspace/school'),
        ]
        for workdir in candidate_dirs:
            for name in ('d2l_current_snapshot.json', 'd2l_grades.json', 'd2l_scraper_output.json'):
                candidate = workdir / name
                if candidate.exists():
                    return candidate
        return candidate_dirs[0] / 'd2l_current_snapshot.json'

    def load_snapshot(self) -> dict[str, Any]:
        path = self._snapshot_path()
        if not path.exists():
            return {"courses": [], "source_path": str(path), "missing": True}
        data = json.loads(path.read_text())
        if isinstance(data, dict):
            data["source_path"] = str(path)
            return data
        return {"courses": [], "source_path": str(path), "missing": True}

    def _normalize_courses(self, snapshot: dict[str, Any]) -> list[dict[str, Any]]:
        items = []
        for course in snapshot.get("courses", []):
            items.append({
                "id": str(course.get("id")),
                "d2l_course_id": str(course.get("id")),
                "name": course.get("name"),
                "code": course.get("code"),
                "finalSummary": course.get("finalSummary"),
                "gradeItemCount": course.get("gradeItemCount"),
                "synced_at": self.store.now(),
            })
        return items

    def _normalize_assignments(self, snapshot: dict[str, Any]) -> list[dict[str, Any]]:
        items = []
        for course in snapshot.get("courses", []):
            course_id = str(course.get("id"))
            for grade_item in course.get("gradeItems", []):
                if grade_item.get("isCategory"):
                    continue
                title = grade_item.get("name") or "Untitled"
                items.append({
                    "id": f"{course_id}:{title.lower().strip()}",
                    "course_id": course_id,
                    "course_name": course.get("name"),
                    "title": title,
                    "points": grade_item.get("points"),
                    "grade": grade_item.get("grade"),
                    "comments": grade_item.get("comments"),
                    "source": "d2l-grade-item",
                    "synced_at": self.store.now(),
                })
        return items

    def sync_to_store(self) -> dict[str, Any]:
        snapshot = self.load_snapshot()
        courses = self._normalize_courses(snapshot)
        assignments = self._normalize_assignments(snapshot)
        existing_assignments = {item.get('id'): item for item in self.repo.list_assignments()}
        for item in assignments:
            prior = existing_assignments.get(item['id']) or {}
            item['status'] = prior.get('status', 'assigned')
            item['updated_at'] = self.store.now()
            item['created_at'] = prior.get('created_at', self.store.now())
        self.repo.replace_courses(courses)
        self.repo.replace_assignments(assignments)
        sync_runs = self.repo.list_sync_runs()
        sync_runs.append({
            "id": self.store.new_id("sync"),
            "snapshot_path": snapshot.get("source_path"),
            "course_count": len(courses),
            "assignment_count": len(assignments),
            "completed_at": self.store.now(),
            "status": "completed",
        })
        self.repo.save_sync_runs(sync_runs)
        grade_note_results = []
        try:
            from app.services.paperless import PaperlessService
            paperless = PaperlessService()
            for item in assignments:
                result = paperless.append_grade_note_if_available(str(item.get("id")))
                if result.get("status") != "skipped":
                    grade_note_results.append(result)
        except Exception as exc:
            grade_note_results.append({"status": "error", "reason": str(exc)})
        return {
            "status": "ok",
            "snapshot_path": snapshot.get("source_path"),
            "course_count": len(courses),
            "assignment_count": len(assignments),
            "backend": self.repo.backend,
            "grade_note_results": grade_note_results,
        }

    def get_courses(self) -> list[dict[str, Any]]:
        items = self.repo.list_courses()
        if items:
            return items
        self.sync_to_store()
        return self.repo.list_courses()

    def get_assignments(self, course_id: str) -> list[dict[str, Any]]:
        items = self.repo.list_assignments()
        if not items:
            self.sync_to_store()
            items = self.repo.list_assignments()
        return [item for item in items if str(item.get("course_id")) == str(course_id)]

    def get_grades(self, course_id: str) -> dict[str, Any]:
        snapshot = self.load_snapshot()
        for course in snapshot.get("courses", []):
            if str(course.get("id")) == str(course_id):
                return {
                    "course_id": str(course.get("id")),
                    "course_name": course.get("name"),
                    "final": course.get("final"),
                    "finalSummary": course.get("finalSummary"),
                    "gradeItems": course.get("gradeItems", []),
                }
        return {"course_id": course_id, "gradeItems": []}

    def describe_sync_plan(self) -> dict:
        snapshot = self.load_snapshot()
        return {
            "status": "stub",
            "backend": self.repo.backend,
            "scraper_workdir": settings.d2l_scraper_workdir,
            "scraper_command": settings.d2l_scraper_command,
            "snapshot_path": snapshot.get("source_path"),
            "course_count": len(snapshot.get("courses", [])),
            "message": "Run existing D2L scraper, normalize courses/assignments/grades, then store into Schoolhouse persistence.",
        }
