#! /usr/bin/env python3

# fmt:off
import sys
import os
from pathlib import Path
sys.path.append((Path(os.environ["EWCONFIG_ROOT"]) / "python_modules").as_posix())
# fmt:on

import argparse
import sys
import logging
import requests
from pathlib import Path
from dataclasses import dataclass, field
from typing import List, Optional, Dict, Any
from ewconfig.secret_manager import get_semi_secret_string
from ewconfig.trello import TRELLO_API_KEY, get_trello_api_token
from ewconfig.trello.cards import get_all_trello_cards, create_card, add_attachment
from ewconfig.trello.boards import PERSONAL_TASKS_BOARD

logger = logging.getLogger(__name__)

GITHUB_API_VERSION = "2022-11-28"
GITHUB_PAT = get_semi_secret_string("github_pat", namespace="trello-sync")
TRELLO_API_TOKEN = get_trello_api_token()


def get_all_issues() -> List[Dict[str, Any]]:
    issues = []

    # Get all issues assigned to me
    response = requests.get(
        "https://api.github.com/issues",
        headers={
            "Authorization": f"token {GITHUB_PAT}",
            "Accept": "application/vnd.github.raw+json",
            "X-GitHub-Api-Version": GITHUB_API_VERSION,
        },
        params={"state": "open", "per_page": 100},
    )
    response.raise_for_status()
    issues.extend(response.json())

    # Get all issues that mention me
    response = requests.get(
        "https://api.github.com/user/issues",
        headers={
            "Authorization": f"token {GITHUB_PAT}",
            "Accept": "application/vnd.github.raw+json",
            "X-GitHub-Api-Version": GITHUB_API_VERSION,
        },
        params={"state": "open", "per_page": 100, "filter": "mentioned"},
    )
    response.raise_for_status()
    issues.extend(response.json())
    
    # Get all issues that exist in my repos
    response = requests.get(
        "https://api.github.com/user/issues",
        headers={
            "Authorization": f"token {GITHUB_PAT}",
            "Accept": "application/vnd.github.raw+json",
            "X-GitHub-Api-Version": GITHUB_API_VERSION,
        },
        params={"state": "open", "per_page": 100, "filter": "repos"},
    )
    response.raise_for_status()
    issues.extend(response.json())
    
    # Get all issues that I have made in other people's repos
    response = requests.get(
        "https://api.github.com/user/issues",
        headers={
            "Authorization": f"token {GITHUB_PAT}",
            "Accept": "application/vnd.github.raw+json",
            "X-GitHub-Api-Version": GITHUB_API_VERSION,
        },
        params={"state": "open", "per_page": 100, "filter": "subscribed"},
    )
    response.raise_for_status()
    issues.extend(response.json())

    # De-dupe issues
    issues = list({issue["id"]: issue for issue in issues}.values())

    return issues


def main() -> int:
    # Handle program arguments
    ap = argparse.ArgumentParser(prog="", description="")
    ap.add_argument("--dry-run", help="Don't actually do anything", action="store_true")
    ap.add_argument(
        "-v", "--verbose", help="Enable verbose logging", action="store_true"
    )
    args = ap.parse_args()

    # Configure logging
    logging.basicConfig(
        level=logging.DEBUG if args.verbose else logging.INFO,
        format="%(levelname)s:	%(message)s",
    )

    # Get a list of all issues assigned to me
    my_issues = get_all_issues()
    logger.info(f"Found {len(my_issues)} issues assigned to me")

    # Get all cards on the personal tasks board
    trello_cards = get_all_trello_cards(
        board_id=PERSONAL_TASKS_BOARD.id,
        api_key=TRELLO_API_KEY,
        api_token=TRELLO_API_TOKEN,
    )
    logger.info(f"Found {len(trello_cards)} cards in Trello")

    # Handle each GitHub issue
    for issue in my_issues:
        # Ignore archived repos
        if issue["repository"]["archived"]:
            logger.info(f"Ignoring archived repo: {issue['repository']['full_name']}")
            continue
        
        # Ignore anything by dependabot
        if issue["user"]["login"] == "dependabot[bot]":
            logger.debug(f"Ignoring dependabot issue: {issue['repository']['full_name']}#{issue['number']}")
            continue

        # Search each card for anything that links to the github issue
        for card in trello_cards:
            if issue["html_url"] in card["desc"]:
                logger.info(
                    f"Found GitHub Issue {issue['number']} in Trello Card {card['id']}"
                )
                break
        else:
            logger.info(
                f"Going to create trello card for GitHub Issue: [{issue['repository']['full_name']}] {issue['title']}"
            )
            if not args.dry_run:
                # Check if this is an issue or pr
                is_pr = "pull_request" in issue
                type_label = (
                    PERSONAL_TASKS_BOARD.tags["Github: Pull Request"]
                    if is_pr
                    else PERSONAL_TASKS_BOARD.tags["Github: Issue"]
                )

                # Create a new trello card for this issue
                card_id = create_card(
                    list_id=PERSONAL_TASKS_BOARD.lists["To Do"],
                    name=f"[{issue['repository']['full_name']}] {issue['title']}",
                    description=(
                        f"**GitHub Link:** [`{issue['repository']['full_name']}#{issue['number']}`]({issue['html_url']})\n\n"
                        f"**Author:** [`{issue['user']['login']}`]({issue['user']['html_url']})\n\n"
                        "---"
                    ),
                    label_ids=[type_label],
                    api_key=TRELLO_API_KEY,
                    api_token=TRELLO_API_TOKEN,
                )
                add_attachment(
                    card_id=card_id,
                    api_key=TRELLO_API_KEY,
                    api_token=TRELLO_API_TOKEN,
                    url=issue["html_url"],
                )
                logger.info(
                    f"Created Trello Card {card_id} for GitHub Issue {issue['repository']['full_name']}#{issue['number']}"
                )

    return 0


if __name__ == "__main__":
    sys.exit(main())