package storage

import (
	"context"
	"errors"
	"fmt"
	"log"
	"madsky.ru/go-tracker/internal/database"
	"madsky.ru/go-tracker/internal/model/status"
)

type StatusRepository interface {
	Find(ctx context.Context) ([]*status.Status, error)
	FindOne(ctx context.Context, id uint64) (*status.Status, error)
	Create(ctx context.Context, dto *status.CreateStatusDTO) (*status.Status, error)
	Update(ctx context.Context, id uint64, issue *status.Status) error
	Remove(ctx context.Context, id uint64) (uint64, error)
}

type StatusStore struct {
	client database.Client
}

func (r *StatusStore) Find(ctx context.Context) ([]*status.Status, error) {
	query := "select id, name, description, position from statuses"

	rows, err := r.client.Query(ctx, query)
	if err != nil {
		log.Println("rows", err)
		return nil, err
	}

	statuses := make([]*status.Status, 0)

	for rows.Next() {
		var n status.Status

		err = rows.Scan(&n.ID, &n.Name, &n.Description, &n.Position)
		if err != nil {
			log.Println("scan", err)
			return nil, err
		}
		statuses = append(statuses, &n)
	}

	if err = rows.Err(); err != nil {
		log.Println("rows err", err)
		return nil, err
	}

	return statuses, nil
}

func (r *StatusStore) FindOne(ctx context.Context, id uint64) (*status.Status, error) {
	query := "select id, name, description, position from statuses where id = $1"

	var s status.Status
	if err := r.client.QueryRow(ctx, query, id).Scan(&s.ID, &s.Name, &s.Description, &s.Position); err != nil {
		fmt.Println(err)
		return nil, err
	}

	return &s, nil
}

func (r *StatusStore) Create(ctx context.Context, dto *status.CreateStatusDTO) (*status.Status, error) {
	q := "insert into statuses (name, description) values ($1, $2) returning id, name, description, position"

	var s status.Status

	if err := r.client.QueryRow(ctx, q, dto.Name, dto.Description).Scan(&s.ID, &s.Name, &s.Description, &s.Position); err != nil {
		fmt.Println(fmt.Sprintf("error %v", err))
		return nil, err
	}
	return &s, nil
}

func (r *StatusStore) Update(ctx context.Context, id uint64, issue *status.Status) error {
	//TODO implement me
	panic("implement me")
}

func (r *StatusStore) Remove(ctx context.Context, id uint64) (uint64, error) {
	q := "delete from statuses where id=$1"

	tag, err := r.client.Exec(ctx, q, id)
	if err != nil {
		log.Println("exec error", err)
		return 0, err
	}

	rowsAffected := tag.RowsAffected()

	if rowsAffected == 0 {
		return 0, errors.New("status not found")
	}

	return uint64(rowsAffected), nil
}
