import { Box, Text, useApp } from 'ink'
import Spinner from 'ink-spinner'
import React, { useEffect, useState } from 'react'
import { filterInactiveRepositories, sortByInactivity } from '../lib/filters.js'
import { GitHubClient } from '../lib/github.js'
import type { AppState, GitHubOptions } from '../types/index.js'
import { Confirm } from './Confirm.js'
import { RepoList } from './RepoList.js'

interface AppProps {
  options: GitHubOptions
}

export const App: React.FC<AppProps> = ({ options }) => {
  const { exit } = useApp()
  const [state, setState] = useState<AppState>({
    loading: true,
    loadingMessage: 'Loading repositories...',
    repositories: [],
    selectedRepos: [],
    error: null,
    confirmMode: false,
    updating: false,
    updatedCount: 0,
  })

  useEffect(() => {
    loadRepositories()
  }, [])

  const loadRepositories = async () => {
    try {
      const client = new GitHubClient(options.token)

      // Get user info
      await client.getAuthenticatedUser()

      // Get all public repositories
      setState((prev) => ({
        ...prev,
        loading: true,
        loadingMessage: 'Fetching public repositories...',
      }))
      const repos = await client.getAllPublicRepositories(options.limit)

      // Update loading message
      setState((prev) => ({
        ...prev,
        loadingMessage: `Analyzing ${repos.length} repositories...`,
      }))

      // Filter inactive repositories
      const filtered = await filterInactiveRepositories(repos, client)
      const sorted = sortByInactivity(filtered)

      setState((prev) => ({
        ...prev,
        loading: false,
        repositories: sorted,
        selectedRepos: sorted,
      }))
    } catch (error) {
      setState((prev) => ({
        ...prev,
        loading: false,
        error:
          error instanceof Error ? error.message : 'Unknown error occurred',
      }))
    }
  }

  const handleConfirm = async () => {
    setState((prev) => ({ ...prev, updating: true }))

    const client = new GitHubClient(options.token)
    let successCount = 0

    for (const repo of state.selectedRepos) {
      const success = await client.makeRepositoryPrivate(
        repo.owner.login,
        repo.name,
        options.dryRun,
      )

      if (success) {
        successCount++
        setState((prev) => ({ ...prev, updatedCount: successCount }))
      }
    }

    setState((prev) => ({ ...prev, updating: false }))

    // Show completion message and exit
    const timer = setTimeout(() => {
      exit()
    }, 2000)

    return () => clearTimeout(timer)
  }

  const handleCancel = () => {
    exit()
  }

  if (state.loading) {
    return (
      <Box>
        <Text color="blue">
          <Spinner type="dots" />
        </Text>
        <Text> {state.loadingMessage}</Text>
      </Box>
    )
  }

  if (state.error) {
    return (
      <Box flexDirection="column">
        <Text color="red">Error: {state.error}</Text>
        <Text dimColor>
          Make sure your GitHub token is valid and has the necessary
          permissions.
        </Text>
      </Box>
    )
  }

  if (state.updating) {
    return (
      <Box flexDirection="column">
        <Box>
          <Text color="blue">
            <Spinner type="dots" />
          </Text>
          <Text>
            {' '}
            Updating repositories... ({state.updatedCount}/
            {state.selectedRepos.length})
          </Text>
        </Box>
        {options.dryRun && (
          <Text color="yellow">
            Running in dry-run mode - no changes will be made
          </Text>
        )}
      </Box>
    )
  }

  if (state.updatedCount > 0) {
    return (
      <Box flexDirection="column">
        <Text color="green">
          ✓ Successfully updated {state.updatedCount} repositories to private!
        </Text>
        {options.dryRun && (
          <Text color="yellow">
            This was a dry run - no actual changes were made
          </Text>
        )}
      </Box>
    )
  }

  return (
    <Box flexDirection="column">
      <Text bold color="cyan">
        GitHub Repository Cleanup Tool
      </Text>

      <RepoList
        repositories={state.repositories}
        title="Inactive Public Repositories"
      />

      {state.repositories.length > 0 && !state.confirmMode && (
        <Box marginTop={1}>
          <Text color="yellow">
            Press Enter to proceed with making these repositories private
          </Text>
        </Box>
      )}

      {state.repositories.length > 0 && (
        <Confirm
          message={`Are you sure you want to make ${state.repositories.length} repositories private?`}
          onConfirm={handleConfirm}
          onCancel={handleCancel}
        />
      )}
    </Box>
  )
}
