#!/usr/bin/python3

# parolottero-languages
# Copyright (C) 2020-2026 Salvo "LtWorf" Tomaselli
#
# parolottero-languages is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero 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 Affero General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
# author Salvo "LtWorf" Tomaselli <tiposchi@tiscali.it>


# This is copy pasted from typedload's example.py

from datetime import datetime
import json
from typing import *
import urllib.request
from pathlib import Path
import subprocess

import typedload.dataloader


def get_data() -> Any:
    """
    Use the github API to get issues information
    """
    url = 'https://codeberg.org/api/v1/repos/parolottero/parolottero-languages/issues?state=open'
    req = urllib.request.Request(url)
    req.add_header('accept', 'application/json')
    with urllib.request.urlopen(req) as f:
        return json.load(f)


class User(NamedTuple):
    login: str


class Issue(NamedTuple):
    number: int
    title: str
    body: str
    user: User
    created_at: datetime
    updated_at: datetime

    @property
    def autoissue(self) -> bool:
        return \
            self.title.startswith('User report for ') and \
            'id: ' in self.body and \
            'Item count: ' in self.body and \
            'Language: ' in self.body

    def _prefix(self, prefix: str) -> Iterable[str]:
        for l in self.body.split('\n'):
            if l.startswith(prefix):
                yield l.strip()

    def diff(self) -> Iterable[str]:
        yield from self._prefix('+')
        yield from self._prefix('-')

    @property
    def language(self) -> str:
        return next(self._prefix('Language: ')).split(' ', 1)[-1]

    @property
    def extrafile(self) -> Path:
        a = {
            'Sicilianu': 'extralist/sicilian.extra',
            'Italiano': 'extralist/italian.extra',
            'English': 'extralist/english.extra',
            'Français': 'extralist/french.extra',
        }
        return Path(a[self.language])

    @property
    def rejectfile(self) -> Path:
        a = {
            'Sicilianu': 'extralist/reject_sicilian.extra',
            'Italiano': 'extralist/reject_italian.extra',
            'English': 'extralist/reject_english.extra',
            'Français': 'extralist/reject_french.extra',
        }
        return Path(a[self.language])

    @property
    def machineid(self) -> str:
        return next(self._prefix('id: ')).split(' ', 1)[-1]

    def __str__(self) -> str:
        return f'#{self.number}: {self.language}\nAutomatic: {self.autoissue} From machine: {self.machineid}\n'


def interactive_fix_issue(issue: Issue) -> None:
    with issue.rejectfile.open('rt') as f:
        rejected = {i.strip() for i in f}
    with issue.extrafile.open('rt') as f:
        extras = {i.strip() for i in f}

    print(f'===== Doing extra words for {issue.language}')
    for diff in issue.diff():
        if diff in extras or diff in rejected:
            continue
        reply = input(f'Is this valid "{diff}" [yN]? ')
        if reply in {'y', 'Y', 'YES', 'yes'}:
            extras.add(diff)
        else:
            with issue.rejectfile.open('at') as f:
                print(diff, file=f)
                rejected.add(diff)

    with issue.extrafile.open('wt') as f:
        wlist = list(extras)
        wlist.sort()
        for l in wlist:
            print(l, file=f)

    subprocess.check_call(['git', 'add', issue.extrafile])
    try:
        subprocess.check_call(['git', 'commit', '-m', f'Fix user reported mistakes\nCloses: #{issue.number}', issue.extrafile])
    except subprocess.CalledProcessError:
        pass
        # TODO close the issue via API


def main():
    data = get_data()

    loader = typedload.dataloader.Loader()

    # We know what the API returns so we can load the json into typed data
    issues = loader.load(data, list[Issue])
    for i in issues:
        if i.autoissue:
            interactive_fix_issue(i)


if __name__ == '__main__':
    main()
