package main

import (
	"flag"
	"fmt"
	"log"
	"os"

	sqliterepo "git.vakhrushev.me/av/transcriber/internal/adapter/repo/sqlite"
	"git.vakhrushev.me/av/transcriber/internal/config"
	"git.vakhrushev.me/av/transcriber/internal/entity"
	"git.vakhrushev.me/av/transcriber/internal/ident"
)

// stepResume — чем возврат в работу подписывается в журнале событий записи.
const stepResume = "resume"

// runResume возвращает остановленную запись в работу.
//
// Подкоманда встала на место панели владельца: панели у сервиса больше нет, а
// экраны правки записи приносят отдельные задачи. Из всего, что владелец делал
// панелью, отложить до экранов нельзя было одно — возврат остановленной записи.
//
// **Колонок подкоманда не пишет.** Перечень полей, которые возврат обязан
// сбросить — признак остановки, признак захвата и срок его протухания, число
// отказов, паузу и время входа в рубеж, — исполняет домен одним действием.
// Рука, забывшая любое из них, оставила бы запись либо невидимой для захвата,
// либо останавливаемой снова первым же захватом — молча, без единой строки.
//
// Событие журнала записи пишется с происхождением «человек»: иначе запись,
// побывавшая остановленной и вернувшаяся в работу, неотличима в журнале от
// записи, которую конвейер вёл без остановок, а происхождение события перестаёт
// различать что-либо.
func runResume(args []string) {
	flags := flag.NewFlagSet("resume", flag.ExitOnError)
	configPath := flags.String("c", "config.toml", "путь к файлу настроек")
	if err := flags.Parse(args); err != nil {
		os.Exit(2)
	}

	if flags.NArg() != 1 {
		fmt.Fprint(os.Stderr, "укажи идентификатор записи: devtools resume [-c config.toml] <id>\n")
		os.Exit(2)
	}

	recordID, ok := ident.Parse(flags.Arg(0))
	if !ok {
		log.Fatalf("идентификатор записи не читается: %q", flags.Arg(0))
	}

	cfg, err := config.LoadConfig(*configPath)
	if err != nil {
		log.Fatalf("настройки не читаются: %v", err)
	}
	if err := cfg.Storage.Validate(); err != nil {
		log.Fatalf("настройки хранилища негодны: %v", err)
	}

	db, err := sqliterepo.Open(cfg.Storage.DataDir, sqliterepo.Settings{
		BusyTimeoutMs:   cfg.Storage.BusyTimeoutMs,
		ReadConnections: cfg.Storage.ReadConnections,
	})
	if err != nil {
		log.Fatalf("база не открывается: %v", err)
	}
	defer func() {
		if err := db.Close(); err != nil {
			log.Printf("база закрылась с отказом: %v", err)
		}
	}()

	records := sqliterepo.NewAudioRecordRepository(db)
	events := sqliterepo.NewRecordEventRepository(db)

	record, err := records.Get(recordID)
	if err != nil {
		log.Fatalf("запись не читается: %v", err)
	}
	if !record.IsHalted() {
		log.Fatalf("запись %s не остановлена: возвращать в работу нечего", recordID)
	}

	// Захват снимает сам домен, поэтому сохранение идёт **безусловным**: держателя
	// у остановленной записи нет, и сверять признак захвата не с чем.
	record.Resume()
	if err := records.Save(record, ""); err != nil {
		log.Fatalf("запись не сохраняется: %v", err)
	}

	if err := events.Append(&entity.RecordEvent{
		RecordID: recordID,
		Origin:   entity.EventOriginHuman,
		Step:     stepResume,
		Outcome:  entity.EventOutcomeResumed,
	}); err != nil {
		log.Fatalf("событие журнала записи не сохраняется: %v", err)
	}

	log.Printf("запись %s возвращена в работу с рубежа %s", recordID, record.State)
}
