package applications_repo

import (
	"context"
	"errors"
	"evening_detective_server/internal/repos"

	"github.com/jackc/pgx/v5/pgxpool"
)

var (
	ErrApplicationNotFound = errors.New("Улика не найдена")
)

type ApplicationsRepo struct {
	pool *pgxpool.Pool
}

func NewApplicationsRepo(pool *pgxpool.Pool) *ApplicationsRepo {
	return &ApplicationsRepo{
		pool: pool,
	}
}

func (r *ApplicationsRepo) AddApplication(
	ctx context.Context,
	teamId int,
	name string,
	image string,
	fileType string,
) (int, error) {
	id := 0
	err := r.pool.QueryRow(
		ctx,
		`INSERT INTO applications (name, image, file_type, team_id)
		VALUES ($1, $2, $3, $4)
		RETURNING id`,
		name,
		image,
		fileType,
		teamId,
	).Scan(&id)

	if err != nil {
		return 0, err
	}
	return id, nil
}

func (r *ApplicationsRepo) GetApplicationsByTeamIDsAndState(
	ctx context.Context,
	teamIds []int,
	state string,
) (map[int][]*repos.Application, error) {
	rows, err := r.pool.Query(
		ctx,
		`SELECT 
			name,
			image,
			file_type,
			team_id
		FROM applications
		WHERE team_id = ANY($1) and status = $2`,
		teamIds,
		state,
	)
	if err != nil {
		return nil, err
	}
	defer rows.Close()

	res := make(map[int][]*repos.Application, len(teamIds))
	for rows.Next() {
		application := &repos.Application{}
		err := rows.Scan(
			&application.Name,
			&application.Image,
			&application.FileType,
			&application.TeamId,
		)
		if err != nil {
			return nil, err
		}
		res[application.TeamId] = append(res[application.TeamId], application)
	}
	if err := rows.Err(); err != nil {
		return nil, err
	}

	return res, nil
}

func (r *ApplicationsRepo) UpdateApplicationStatus(
	ctx context.Context,
	teamId int,
	name string,
	status string,
) error {
	tag, err := r.pool.Exec(
		ctx,
		`UPDATE applications
		SET 
			status = $1
		WHERE team_id = $2 and name = $3`,
		status,
		teamId,
		name,
	)
	if err != nil {
		return err
	}
	if tag.RowsAffected() == 0 {
		return ErrApplicationNotFound
	}
	return nil
}

func (r *ApplicationsRepo) DeleteApplicationByTeamIdAndName(ctx context.Context, teamId int, name string) error {
	tag, err := r.pool.Exec(
		ctx,
		`DELETE FROM applications
		WHERE id IN (
			SELECT id 
			FROM applications 
			WHERE team_id = $1 and name = $2
			ORDER BY created_at DESC 
			LIMIT 1
		)`,
		teamId,
		name,
	)
	if err != nil {
		return err
	}
	if tag.RowsAffected() == 0 {
		return ErrApplicationNotFound
	}
	return nil
}
