package main

import (
	"database/sql"
	"fmt"
	"os"
	"path/filepath"

	_ "modernc.org/sqlite"
)

func initDB(cfg Config) (*sql.DB, error) {
	if err := os.MkdirAll(filepath.Dir(cfg.DBPath), 0o755); err != nil {
		return nil, fmt.Errorf("create data dir: %w", err)
	}

	db, err := sql.Open("sqlite", cfg.DBPath)
	if err != nil {
		return nil, fmt.Errorf("open sqlite: %w", err)
	}

	db.SetMaxOpenConns(1)
	db.SetMaxIdleConns(1)

	if _, err := db.Exec(`
PRAGMA foreign_keys = ON;
PRAGMA journal_mode = WAL;
PRAGMA busy_timeout = 5000;
`); err != nil {
		return nil, fmt.Errorf("sqlite pragmas: %w", err)
	}

	schema := `
CREATE TABLE IF NOT EXISTS players (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  name_ar TEXT NOT NULL,
  name_en TEXT NOT NULL,
  group_code TEXT NOT NULL DEFAULT '',
  image_data TEXT NOT NULL DEFAULT '',
  created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
  updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
);

CREATE TABLE IF NOT EXISTS scores (
  stage TEXT NOT NULL,
  player_id INTEGER NOT NULL,
  score INTEGER NOT NULL DEFAULT 0,
  updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY(stage, player_id),
  FOREIGN KEY(player_id) REFERENCES players(id) ON DELETE CASCADE
);

CREATE TABLE IF NOT EXISTS score_attachments (
  stage TEXT NOT NULL,
  player_id INTEGER NOT NULL,
  image_data TEXT NOT NULL DEFAULT '',
  updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY(stage, player_id),
  FOREIGN KEY(player_id) REFERENCES players(id) ON DELETE CASCADE
);

CREATE TABLE IF NOT EXISTS app_settings (
  key TEXT PRIMARY KEY,
  value TEXT NOT NULL DEFAULT '',
  updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
);

INSERT OR IGNORE INTO app_settings(key, value) VALUES
  ('view_proof_in_view', '0'),
  ('live_active_view', 'group_live'),
  ('live_show_group_live', '1'),
  ('live_group_display_mode', 'rotate'),
  ('live_group_fixed_code', ''),
  ('live_show_prelim_tie', '1'),
  ('live_show_prelim_overall', '1'),
  ('live_show_final_groups', '1'),
  ('live_final_display_mode', 'rotate'),
  ('live_final_fixed_group', '1'),
  ('live_show_final_tie', '1'),
  ('live_show_podium', '1'),
  ('live_rotation_interval_sec', '5'),
  ('live_rotation_player_count', '12');

INSERT OR IGNORE INTO scores(stage, player_id, score)
SELECT 'prelim_r1', player_id, score FROM scores WHERE stage = 'preliminary';
INSERT OR IGNORE INTO scores(stage, player_id, score)
SELECT 'final_r1', player_id, score FROM scores WHERE stage = 'final';

INSERT OR IGNORE INTO score_attachments(stage, player_id, image_data)
SELECT 'prelim_r1', player_id, image_data FROM score_attachments WHERE stage = 'preliminary';
INSERT OR IGNORE INTO score_attachments(stage, player_id, image_data)
SELECT 'final_r1', player_id, image_data FROM score_attachments WHERE stage = 'final';
`
	if _, err := db.Exec(schema); err != nil {
		return nil, fmt.Errorf("apply schema: %w", err)
	}

	return db, nil
}
