// Package dao 提供 transcribe 模块的数据库访问操作
package dao

import (
	"context"
	"errors"
	"time"

	"github.com/echochat/backend/app/transcribe/model"
	"gorm.io/gorm"
)

// TranscriptDAO 转写记录数据访问对象（PostgreSQL 主库）
type TranscriptDAO struct {
	db *gorm.DB
}

// NewTranscriptDAO 创建实例
func NewTranscriptDAO(db *gorm.DB) *TranscriptDAO {
	return &TranscriptDAO{db: db}
}

// GetByRecordingID 按 recording_id 获取转写记录（不存在返回 nil, nil）
//
// 之所以 nil 不视为错误：调用方常见模式是"取不到 → 创建新行"，避免 ErrRecordNotFound 包装
func (d *TranscriptDAO) GetByRecordingID(ctx context.Context, recordingID int64) (*model.Transcript, error) {
	var t model.Transcript
	err := d.db.WithContext(ctx).
		Where("recording_id = ?", recordingID).
		First(&t).Error
	if err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return nil, nil
		}
		return nil, err
	}
	return &t, nil
}

// ListByRoomID 拉取一场会议下所有转写（按 recording_id 升序）
// 用于会议详情页一次性带回多段录制的转写状态
func (d *TranscriptDAO) ListByRoomID(ctx context.Context, roomID int64) ([]model.Transcript, error) {
	var list []model.Transcript
	err := d.db.WithContext(ctx).
		Where("room_id = ?", roomID).
		Order("recording_id ASC").
		Find(&list).Error
	return list, err
}

// Upsert 插入或更新（按 recording_id unique 索引）
// 用于"重新转写"路径：保留同一行 ID，状态/文本就地刷新
func (d *TranscriptDAO) Upsert(ctx context.Context, t *model.Transcript) error {
	existing, err := d.GetByRecordingID(ctx, t.RecordingID)
	if err != nil {
		return err
	}
	if existing == nil {
		return d.db.WithContext(ctx).Create(t).Error
	}
	t.ID = existing.ID
	return d.db.WithContext(ctx).Save(t).Error
}

// MarkRunning 把指定 transcript 置为 running 状态，并填 started_at = now
//
// 用于异步任务起跑时的状态翻转，保证后端重启时 running 行不会卡死
// （配合 RescueStuckRunning 兜底）。
func (d *TranscriptDAO) MarkRunning(ctx context.Context, id int64) error {
	now := time.Now()
	return d.db.WithContext(ctx).
		Model(&model.Transcript{}).
		Where("id = ?", id).
		Updates(map[string]any{
			"status":     model.TranscriptStatusRunning,
			"started_at": now,
			"error_msg":  "",
		}).Error
}

// MarkReady 转写成功
func (d *TranscriptDAO) MarkReady(ctx context.Context, id int64, text, segments, language string, durationSec int) error {
	now := time.Now()
	return d.db.WithContext(ctx).
		Model(&model.Transcript{}).
		Where("id = ?", id).
		Updates(map[string]any{
			"status":       model.TranscriptStatusReady,
			"text":         text,
			"segments":     segments,
			"language":     language,
			"duration_sec": durationSec,
			"finished_at":  now,
			"error_msg":    "",
		}).Error
}

// MarkFailed 转写失败
func (d *TranscriptDAO) MarkFailed(ctx context.Context, id int64, errorMsg string) error {
	now := time.Now()
	if len(errorMsg) > 500 {
		errorMsg = errorMsg[:500]
	}
	return d.db.WithContext(ctx).
		Model(&model.Transcript{}).
		Where("id = ?", id).
		Updates(map[string]any{
			"status":      model.TranscriptStatusFailed,
			"error_msg":   errorMsg,
			"finished_at": now,
		}).Error
}
