"""Core dataclasses and enums shared across the project."""

from __future__ import annotations
from dataclasses import dataclass
from datetime import datetime
from enum import Enum


class PullStatus(str, Enum):
    """Outcome of a safe pull attempt."""
    UPDATED = "updated"
    ALREADY_UP_TO_DATE = "already_up_to_date"
    SKIPPED_DIRTY = "skipped_dirty"
    SKIPPED_CONFLICT = "skipped_conflict"
    SKIPPED_AHEAD_ONLY = "skipped_ahead_only"
    ERROR = "error"


class EventType(str, Enum):
    """Type of workspace event detected during a refresh cycle."""
    PIPELINE_FAILED = "pipeline_failed"
    PIPELINE_FIXED = "pipeline_fixed"
    MR_NEW_COMMENT = "mr_new_comment"
    MR_APPROVED = "mr_approved"
    MR_CHANGES_REQUESTED = "mr_changes_requested"
    MR_MERGED = "mr_merged"
    MR_NEW_PUSH = "mr_new_push"
    VULN_NEW = "vuln_new"
    VULN_RESOLVED = "vuln_resolved"
    AUTH_EXPIRED = "auth_expired"
    BRANCH_STALE = "branch_stale"


@dataclass
class Repo:
    """A discovered git repository in the workspace."""
    name: str  # directory name
    path: str  # absolute path
    remote_url: str  # origin URL
    forge_host: str | None  # e.g. "gitlab.com"
    forge_type: str | None  # "gitlab" or None
    has_forge: bool
    project_path: str | None  # e.g. "myunisoft/myu-pa/services/pa-services-gateway"
    default_branch: str | None = None  # e.g. "main", fetched from forge API

    def to_dict(self) -> dict:
        return {
            "name": self.name, "path": self.path, "remote_url": self.remote_url,
            "forge_host": self.forge_host, "forge_type": self.forge_type,
            "has_forge": self.has_forge, "project_path": self.project_path,
            "default_branch": self.default_branch,
        }


@dataclass
class GitStatus:
    """Git branch state: ahead/behind counts, dirty flag, stale detection."""
    branch: str | None
    ahead: int
    behind: int
    dirty: bool
    stale: bool = False  # upstream configured but remote branch deleted (e.g. after merge)


@dataclass
class MR:
    """A GitLab merge request."""
    id: int
    iid: int
    title: str
    author: str
    state: str
    source_branch: str
    target_branch: str
    web_url: str
    user_notes_count: int
    approved: bool
    created_at: str
    updated_at: str
    repo_name: str  # filled by caller, not from API
    sha: str | None = None  # diffHeadSha — tracks new pushes

    def to_dict(self) -> dict:
        return {
            "id": self.id, "iid": self.iid, "title": self.title,
            "author": self.author, "state": self.state,
            "source_branch": self.source_branch, "target_branch": self.target_branch,
            "web_url": self.web_url, "user_notes_count": self.user_notes_count,
            "approved": self.approved, "created_at": self.created_at,
            "updated_at": self.updated_at, "repo_name": self.repo_name, "sha": self.sha,
        }


@dataclass
class Pipeline:
    """A GitLab CI pipeline."""
    id: int
    status: str
    ref: str
    web_url: str
    created_at: str
    repo_name: str

    def to_dict(self) -> dict:
        return {
            "id": self.id, "status": self.status, "ref": self.ref,
            "web_url": self.web_url, "created_at": self.created_at,
            "repo_name": self.repo_name,
        }


@dataclass
class Job:
    """A single job within a GitLab CI pipeline."""
    id: int
    name: str
    status: str
    stage: str
    web_url: str

    def to_dict(self) -> dict:
        return {
            "id": self.id, "name": self.name, "status": self.status,
            "stage": self.stage, "web_url": self.web_url,
        }


@dataclass
class Vulnerability:
    """A security vulnerability reported by GitLab scanners."""
    id: int
    name: str
    severity: str
    state: str
    source: str  # reportType: SAST, DEPENDENCY_SCANNING, etc.
    web_url: str
    repo_name: str
    mitigation_state: str | None = None  # OPEN, RESOLVED, etc.
    mitigation_details: str | None = None
    location: str | None = None  # "file.py:123"
    solution: str | None = None  # scanner-recommended fix
    fixed_in_branch: bool = False  # vuln not found in current branch pipeline findings

    def to_dict(self) -> dict:
        return {
            "id": self.id, "name": self.name, "severity": self.severity,
            "state": self.state, "source": self.source, "web_url": self.web_url,
            "repo_name": self.repo_name, "mitigation_state": self.mitigation_state,
            "mitigation_details": self.mitigation_details,
            "location": self.location, "solution": self.solution,
            "fixed_in_branch": self.fixed_in_branch,
        }


@dataclass
class Event:
    """A workspace event generated by diffing cache state across refreshes."""
    id: int | None  # DB-assigned
    type: EventType
    repo_name: str
    summary: str
    detail: str
    created_at: datetime
    seen: bool = False

    def to_dict(self) -> dict:
        return {
            "id": self.id, "type": self.type.value, "repo_name": self.repo_name,
            "summary": self.summary, "detail": self.detail,
            "created_at": self.created_at.isoformat()
            if isinstance(self.created_at, datetime) else self.created_at,
            "seen": self.seen,
        }


@dataclass
class RepoResult:
    """Result of a git operation (fetch, pull) on a single repo."""
    repo: str
    status: str
    message: str | None = None
