# gophian -- tools to help with Debianizing Go software
# Copyright (C) 2024-2025 Maytham Alsudany <maytha8thedev@gmail.com>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <https://www.gnu.org/licenses/>.

import re
from enum import Enum, auto
from typing import List, Optional, Self

import requests

WNPP_BUG_PATTERN = re.compile(
    r'<a href="https://bugs.debian.org/(?P<id>\d+)">(?P<package>[A-Za-z0-9\-\.]+): (?P<description>[\S ]+)</a>'
)


class WnppBugType(Enum):
    """
    Enum representing the different types of WNPP bugs.
    """

    ITP = auto()
    RFP = auto()


class WnppBug:
    """
    Class to represent a WNPP bug.
    """

    def __init__(
        self, type: WnppBugType, id: str, package: str, description: str
    ) -> None:
        self.type = type
        self.id = id
        self.package = package
        self.description = description


class ITPBug(WnppBug):
    """
    Class to represent an ITP (Intent to Package) bug.
    """

    def __init__(self, id: str, package: str, description: str) -> None:
        self.type = WnppBugType.ITP
        self.id = id
        self.package = package
        self.description = description

    @classmethod
    def all(cls, session: requests.Session) -> List[Self]:
        """
        Fetch a list of all open ITP bugs.
        """
        html = session.get(
            "https://www.debian.org/devel/wnpp/being_packaged", timeout=60
        ).text

        return list(
            map(lambda g: cls(g[0], g[1], g[2]), WNPP_BUG_PATTERN.findall(html))
        )

    @classmethod
    def search(cls, session: requests.Session, package: str) -> List[Self]:
        """
        Search for ITP bugs whose package name contain the given package name.
        """
        itps = cls.all(session)
        return [itp for itp in itps if package in itp.package]

    @classmethod
    def get(cls, session: requests.Session, package: str) -> Optional[Self]:
        """
        Find the ITP bug corresponding to the given package name.
        """
        itps = cls.all(session)
        for itp in itps:
            if package == itp.package:
                return itp
        return None


class RFPBug(WnppBug):
    """
    Class to represent an RFP (Request for Package) bug.
    """

    def __init__(self, id: str, package: str, description: str) -> None:
        self.type = WnppBugType.RFP
        self.id = id
        self.package = package
        self.description = description

    @classmethod
    def all(cls, session: requests.Session) -> List[Self]:
        """
        Fetch a list of all open RFP bugs.
        """
        html = session.get(
            "https://www.debian.org/devel/wnpp/requested", timeout=60
        ).text

        return list(
            map(lambda g: cls(g[0], g[1], g[2]), WNPP_BUG_PATTERN.findall(html))
        )

    @classmethod
    def search(cls, session: requests.Session, package: str) -> List[Self]:
        """
        Search for RFP bugs whose package name contain the given package name.
        """
        rfps = cls.all(session)
        return [rfp for rfp in rfps if package in rfp.package]

    @classmethod
    def get(cls, session: requests.Session, package: str) -> Optional[Self]:
        """
        Find the RFP bug corresponding to the given package name.
        """
        rfps = cls.all(session)
        for rfp in rfps:
            if package == rfp.package:
                return rfp
        return None
