package app

import (
	"fmt"
	"log/slog"
	"os"

	"github.com/ayn2op/discordo/internal/clipboard"
	"github.com/ayn2op/discordo/internal/config"
	"github.com/ayn2op/discordo/internal/consts"
	"github.com/ayn2op/discordo/internal/keyring"
	"github.com/ayn2op/discordo/internal/ui/chat"
	"github.com/ayn2op/discordo/internal/ui/login"
	"github.com/ayn2op/tview"
	"github.com/gdamore/tcell/v3"
)

type App struct {
	inner    *tview.Application
	chatView *chat.View
	cfg      *config.Config
}

func New(cfg *config.Config) *App {
	tview.Styles = tview.Theme{}
	app := &App{
		inner: tview.NewApplication(),
		cfg:   cfg,
	}

	if err := clipboard.Init(); err != nil {
		slog.Error("failed to init clipboard", "err", err)
	}

	app.inner.SetInputCapture(app.onInputCapture)
	return app
}

func (a *App) Run() error {
	token := os.Getenv("DISCORDO_TOKEN")
	if token == "" {
		t, err := keyring.GetToken()
		if err != nil {
			slog.Info("failed to retrieve token from keyring", "err", err)
		}
		token = t
	}

	screen, err := tcell.NewScreen()
	if err != nil {
		return fmt.Errorf("failed to create screen: %w", err)
	}

	if err := screen.Init(); err != nil {
		return fmt.Errorf("failed to init screen: %w", err)
	}

	if a.cfg.Mouse {
		screen.EnableMouse()
	}

	screen.SetTitle(consts.Name)
	screen.EnablePaste()
	screen.EnableFocus()
	a.inner.SetScreen(screen)

	if token == "" {
		loginForm := login.NewForm(a.inner, a.cfg, func(token string) {
			if err := a.showChatView(token); err != nil {
				slog.Error("failed to show chat view", "err", err)
			}
		})
		a.inner.SetRoot(loginForm)
	} else {
		if err := a.showChatView(token); err != nil {
			return err
		}
	}

	return a.inner.Run()
}

func (a *App) showChatView(token string) error {
	a.chatView = chat.NewView(a.inner, a.cfg, a.quit)
	if err := a.chatView.OpenState(token); err != nil {
		return err
	}
	a.inner.SetRoot(a.chatView)
	return nil
}

func (a *App) quit() {
	if a.chatView != nil {
		if err := a.chatView.CloseState(); err != nil {
			slog.Error("failed to close the session", "err", err)
		}
	}

	a.inner.Stop()
}

func (a *App) onInputCapture(event *tcell.EventKey) *tcell.EventKey {
	switch event.Name() {
	case a.cfg.Keybinds.Quit:
		a.quit()
		return nil
	case "Ctrl+C":
		// https://github.com/ayn2op/tview/blob/a64fc48d7654432f71922c8b908280cdb525805c/application.go#L153
		return tcell.NewEventKey(tcell.KeyCtrlC, "", tcell.ModNone)
	}

	return event
}
