package postgres

import (
	"context"
	"database/sql"

	"chat-switchboard/models"
)

type PersonaGroupStore struct{}

func NewPersonaGroupStore() *PersonaGroupStore { return &PersonaGroupStore{} }

const personaGroupCols = `id, name, description, owner_id, scope, team_id, created_at, updated_at`

func (s *PersonaGroupStore) List(ctx context.Context, ownerID string) ([]models.PersonaGroup, error) {
	rows, err := DB.QueryContext(ctx, `
		SELECT `+personaGroupCols+` FROM persona_groups
		WHERE owner_id = $1 ORDER BY name
	`, ownerID)
	if err != nil {
		return nil, err
	}
	defer rows.Close()

	groups := []models.PersonaGroup{}
	for rows.Next() {
		var g models.PersonaGroup
		if err := rows.Scan(&g.ID, &g.Name, &g.Description, &g.OwnerID,
			&g.Scope, &g.TeamID, &g.CreatedAt, &g.UpdatedAt); err != nil {
			continue
		}
		groups = append(groups, g)
	}
	return groups, rows.Err()
}

func (s *PersonaGroupStore) Get(ctx context.Context, id, ownerID string) (*models.PersonaGroup, error) {
	var g models.PersonaGroup
	err := DB.QueryRowContext(ctx, `
		SELECT `+personaGroupCols+` FROM persona_groups WHERE id = $1 AND owner_id = $2
	`, id, ownerID).Scan(&g.ID, &g.Name, &g.Description, &g.OwnerID,
		&g.Scope, &g.TeamID, &g.CreatedAt, &g.UpdatedAt)
	if err == sql.ErrNoRows {
		return nil, nil
	}
	if err != nil {
		return nil, err
	}
	return &g, nil
}

func (s *PersonaGroupStore) Create(ctx context.Context, g *models.PersonaGroup) error {
	return DB.QueryRowContext(ctx, `
		INSERT INTO persona_groups (name, description, owner_id, scope)
		VALUES ($1, $2, $3, $4)
		RETURNING id, name, description, owner_id, scope, team_id, created_at, updated_at
	`, g.Name, g.Description, g.OwnerID, g.Scope).Scan(
		&g.ID, &g.Name, &g.Description, &g.OwnerID,
		&g.Scope, &g.TeamID, &g.CreatedAt, &g.UpdatedAt)
}

func (s *PersonaGroupStore) Update(ctx context.Context, id string, fields map[string]interface{}) error {
	for k, v := range fields {
		_, err := DB.ExecContext(ctx,
			`UPDATE persona_groups SET `+k+` = $1, updated_at = NOW() WHERE id = $2`, v, id)
		if err != nil {
			return err
		}
	}
	return nil
}

func (s *PersonaGroupStore) Delete(ctx context.Context, id, ownerID string) (int64, error) {
	result, err := DB.ExecContext(ctx,
		`DELETE FROM persona_groups WHERE id = $1 AND owner_id = $2`, id, ownerID)
	if err != nil {
		return 0, err
	}
	return result.RowsAffected()
}

func (s *PersonaGroupStore) GetOwnerID(ctx context.Context, id string) (string, error) {
	var ownerID string
	err := DB.QueryRowContext(ctx,
		`SELECT owner_id FROM persona_groups WHERE id = $1`, id).Scan(&ownerID)
	if err == sql.ErrNoRows {
		return "", nil
	}
	return ownerID, err
}

func (s *PersonaGroupStore) AddMember(ctx context.Context, groupID, personaID string, isLeader bool) error {
	if isLeader {
		_, _ = DB.ExecContext(ctx,
			`UPDATE persona_group_members SET is_leader = false WHERE group_id = $1`, groupID)
	}
	_, err := DB.ExecContext(ctx, `
		INSERT INTO persona_group_members (group_id, persona_id, is_leader)
		VALUES ($1, $2, $3)
		ON CONFLICT (group_id, persona_id) DO UPDATE SET is_leader = EXCLUDED.is_leader
	`, groupID, personaID, isLeader)
	return err
}

func (s *PersonaGroupStore) RemoveMember(ctx context.Context, memberID, groupID string) error {
	_, err := DB.ExecContext(ctx,
		`DELETE FROM persona_group_members WHERE id = $1 AND group_id = $2`, memberID, groupID)
	return err
}

func (s *PersonaGroupStore) ListMembers(ctx context.Context, groupID string) ([]models.PersonaGroupMember, error) {
	rows, err := DB.QueryContext(ctx, `
		SELECT pgm.id, pgm.group_id, pgm.persona_id, pgm.is_leader, pgm.sort_order,
		       COALESCE(p.name, '') AS persona_name,
		       COALESCE(p.handle, '') AS persona_handle,
		       COALESCE(p.avatar, '') AS persona_avatar
		FROM persona_group_members pgm
		LEFT JOIN personas p ON p.id = pgm.persona_id
		WHERE pgm.group_id = $1
		ORDER BY pgm.is_leader DESC, pgm.sort_order, pgm.id
	`, groupID)
	if err != nil {
		return []models.PersonaGroupMember{}, nil
	}
	defer rows.Close()

	members := []models.PersonaGroupMember{}
	for rows.Next() {
		var m models.PersonaGroupMember
		if err := rows.Scan(&m.ID, &m.GroupID, &m.PersonaID, &m.IsLeader, &m.SortOrder,
			&m.PersonaName, &m.PersonaHandle, &m.PersonaAvatar); err != nil {
			continue
		}
		members = append(members, m)
	}
	return members, rows.Err()
}
