from textual.app import ComposeResult
from textual.coordinate import Coordinate
from textual.binding import Binding
from textual.screen import Screen
from textual.widgets import DataTable, TabbedContent, TabPane, Header, Footer

from peewee import fn, JOIN

from ..utils import truncate
from ..sync import sync
from ..db import (
    KimaiProject,
    KimaiCustomer,
    KimaiActivity,
)
from ..kimaiapi import Timesheet as KimaiAPITimesheet

from .list import ListPane


class KimaiCustomerList(ListPane):
    pass


class KimaiProjectList(ListPane):
    BINDINGS = [
        ("s", "sort", "Sort"),
        ("r", "refresh", "Refresh"),
        ("g", "get", "Get data"),
        ("/", "filter", "Search"),
        Binding(key="escape", action="cancelfilter", show=False),
    ]

    def _refresh(self):
        self.table.clear()

        filter_search = self.query_one("#filter #search").value

        projects = (
            KimaiProject.select(
                KimaiProject,
                KimaiCustomer.id,
                fn.COALESCE(KimaiCustomer.name, "").alias("customer_name"),
                fn.Count(KimaiActivity.id).alias("activities_count"),
            )
            .join(KimaiCustomer, JOIN.LEFT_OUTER)
            .switch(KimaiProject)
            .join(KimaiActivity, JOIN.LEFT_OUTER)
            .where(KimaiActivity.project.is_null(False))
            .group_by(KimaiProject)
        )

        if filter_search:
            projects = projects.where(
                KimaiProject.name.contains(filter_search)
                | KimaiCustomer.name.contains(filter_search)
            )

        self.table.add_rows(
            [
                [
                    str(project.customer_id) if project.customer_id is not None else "",
                    project.customer_name,
                    project.id,
                    project.name,
                    project.activities_count,
                    project.visible,
                ]
                for project in projects
            ]
        )

        self.table.sort(*self.sort)

    def action_get(self) -> None:
        sync()
        self._refresh()

    def on_mount(self) -> None:
        self.table = self.query_one(DataTable)
        self.table.cursor_type = "row"
        self.columns = self.table.add_columns(
            "customer id", "customer", "project id", "project", "activities", "visible"
        )
        self.sort = (self.columns[1], self.columns[3])
        self._refresh()


class KimaiActivityList(ListPane):
    BINDINGS = [
        ("s", "sort", "Sort"),
        ("r", "refresh", "Refresh"),
        ("g", "get", "Get data"),
        ("#", "count", "Count"),
        ("/", "filter", "Search"),
        Binding(key="escape", action="cancelfilter", show=False),
    ]

    def _refresh(self):
        self.table.clear()

        filter_search = self.query_one("#filter #search").value

        activities = (
            KimaiActivity.select(
                KimaiActivity,
                fn.COALESCE(KimaiProject.name, "").alias("project_name"),
                fn.COALESCE(KimaiCustomer.name, "").alias("customer_name"),
            )
            .join(KimaiProject, JOIN.LEFT_OUTER)
            .join(KimaiCustomer, JOIN.LEFT_OUTER)
            .group_by(KimaiActivity)
        )

        if filter_search:
            activities = activities.where(KimaiActivity.name.contains(filter_search))

        self.table.add_rows(
            [
                [
                    # activity.project.customer_id if activity.project is not None else '',
                    # activity.customer_name,
                    str(activity.project_id) if activity.project_id is not None else "",
                    truncate(activity.project_name, 40),
                    activity.id,
                    truncate(activity.name, 40),
                    activity.visible,
                    "?",
                ]
                for activity in activities
            ]
        )

        self.table.sort(*self.sort)

    def action_get(self) -> None:
        sync()
        self._refresh()

    def on_mount(self) -> None:
        self.table = self.query_one(DataTable)
        self.table.cursor_type = "row"
        self.columns = self.table.add_columns(
            # "customer id",
            # "customer",
            "project id",
            "project",
            "id",
            "name",
            "visible",
            "times",
        )
        self.sort = (self.columns[1], self.columns[3])
        self._refresh()

    def action_count(self) -> None:
        row_idx: int = self.table.cursor_row
        row_cells = self.table.get_row_at(row_idx)

        activity_id = row_cells[2]
        count = len(KimaiAPITimesheet.list_by(self.app.api, activity=activity_id))

        self.table.update_cell_at(Coordinate(row_idx, 5), count)


class KimaiScreen(Screen):
    BINDINGS = [
        ("c", "show_tab('customers')", "Customers"),
        ("p", "show_tab('projects')", "Projects"),
        ("a", "show_tab('activities')", "Activities"),
    ]

    SUB_TITLE = "Kimai"

    def compose(self) -> ComposeResult:
        yield Header()
        with TabbedContent(initial="projects"):
            with TabPane("Customers", id="customers"):
                yield KimaiCustomerList()
            with TabPane("Projects", id="projects"):
                yield KimaiProjectList()
            with TabPane("Activities", id="activities"):
                yield KimaiActivityList()
        yield Footer()

    def on_mount(self) -> None:
        self.query_one("TabbedContent Tabs").can_focus = False
        self.query_one("#projects DataTable").focus()

    def action_show_tab(self, tab: str) -> None:
        """Switch to a new tab."""
        self.get_child_by_type(TabbedContent).active = tab
        self.query_one(f"#{tab} DataTable").focus()