#!/usr/bin/env python3
"""COMP3311 Assignment 2 — ass2 skeleton.

Implement progressively Q1..Q5.

Rules:
- Use psycopg2
- Parameterised queries only
- Deterministic output and ordering
"""

from __future__ import annotations

import re
import sys
from dataclasses import dataclass
from typing import Optional, List, Tuple, Dict, Any

import psycopg2

DAY = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"]


@dataclass
class Term:
    id: int
    unswid: int
    year: int
    term: str
    starting: str
    ending: str


class Shell:
    def __init__(self, dsn: str = "dbname=mymyunsw"):
        self.conn = psycopg2.connect(dsn)
        self.conn.autocommit = False
        self.in_config = False
        self.admin = False
        self.current_term: Optional[Term] = None

    # ---------- Q1 ----------
    def cmd_term(self, sem_unswid: int) -> None:
        raise NotImplementedError

    def cmd_show(self) -> None:
        raise NotImplementedError

    # ---------- Q2 ----------
    def cmd_student(self, zid_raw: str) -> None:
        raise NotImplementedError

    # ---------- Q3 ----------
    def cmd_enrol(self, zid_raw: str, codes: List[str]) -> None:
        raise NotImplementedError

    def cmd_timetable(self, zid_raw: str) -> None:
        raise NotImplementedError

    # ---------- Q4 ----------
    def cmd_plan(self, zid_raw: str, codes: List[str]) -> None:
        raise NotImplementedError

    # ---------- Q5 ----------
    def cmd_offer(self, code: str, expected: int, nlec: int) -> None:
        raise NotImplementedError


def parse_zid(z: str) -> Optional[int]:
    z = z.strip()
    m = re.fullmatch(r"z?(\d{7})", z, flags=re.IGNORECASE)
    if not m:
        return None
    return int(m.group(1))


def main() -> None:
    sh = Shell()

    for line in sys.stdin:
        line = line.strip()
        if not line:
            continue

        parts = line.split()
        cmd = parts[0].lower()

        try:
            if cmd in ("/c", "/d"):
                sh.in_config = True
                continue
            if cmd == "exit":
                sh.in_config = False
                continue
            if cmd == "show":
                sh.cmd_show()
                continue
            if cmd == "term":
                sh.cmd_term(int(parts[1]))
                continue
            if cmd == "student":
                sh.cmd_student(parts[1])
                continue
            if cmd == "enrol":
                sh.cmd_enrol(parts[1], parts[2:])
                continue
            if cmd == "timetable":
                sh.cmd_timetable(parts[1])
                continue
            if cmd == "plan":
                sh.cmd_plan(parts[1], parts[2:])
                continue
            if cmd == "admin":
                if len(parts) != 2 or parts[1].lower() not in ("on", "off"):
                    print("Usage: admin on|off")
                else:
                    sh.admin = (parts[1].lower() == "on")
                continue
            if cmd == "offer":
                sh.cmd_offer(parts[1], int(parts[2]), int(parts[3]))
                continue

            print("Unknown command.")

        except Exception:
            sh.conn.rollback()
            raise


if __name__ == "__main__":
    main()
