package main

import (
	"database/sql"
	"encoding/json"
	"fmt"
	"os"
	"path/filepath"
	"strings"
	"time"

	_ "modernc.org/sqlite"
)

type Image struct {
	ImageURL string `json:"image_url"`
	Title    string `json:"title"`
}

type SnippetData struct {
	RelatedKW   []string `json:"related_kw"`
	Description []string `json:"description"`
}

type SnippetArticle struct {
	ID          int
	Keyword     string
	Slug        string
	Images      []Image
	Snippet     SnippetData
	RawSnippet  string
	CreatedAt   string
}

func streamSnippetArticles(dataFolder string, batchSize int, out chan<- SnippetArticle, errChan chan<- error) {
	defer close(out)

	absPath := projectPath(dataFolder)
	entries, err := os.ReadDir(absPath)
	if err != nil {
		errChan <- fmt.Errorf("error reading data folder %s: %w", absPath, err)
		return
	}

	for _, entry := range entries {
		if entry.IsDir() {
			continue
		}
		ext := strings.ToLower(filepath.Ext(entry.Name()))
		if ext != ".db" && ext != ".sqlite" {
			continue
		}

		dbPath := filepath.Join(absPath, entry.Name())
		db, err := sql.Open("sqlite", dbPath)
		if err != nil {
			errChan <- fmt.Errorf("error opening database %s: %w", dbPath, err)
			return
		}

		lastID := 0
		for {
			query := `
				SELECT id, keyword, slug, images, snippet, created_at 
				FROM posts 
				WHERE id > ?
					AND images IS NOT NULL AND images != '' AND images != '[]'
					AND snippet IS NOT NULL AND TRIM(snippet) != ''
				ORDER BY id ASC
				LIMIT ?
			`
			rows, err := db.Query(query, lastID, batchSize)
			if err != nil {
				db.Close()
				errChan <- fmt.Errorf("error querying database: %w", err)
				return
			}

			fetched := false
			for rows.Next() {
				var (
					id         int
					keyword    string
					slug       string
					imagesJSON string
					snippet    string
					createdAt  string
				)

				if err := rows.Scan(&id, &keyword, &slug, &imagesJSON, &snippet, &createdAt); err != nil {
					rows.Close()
					db.Close()
					errChan <- fmt.Errorf("error scanning row: %w", err)
					return
				}

				fetched = true
				lastID = id

				var images []Image
				if err := json.Unmarshal([]byte(imagesJSON), &images); err != nil {
					images = []Image{}
				}

				var snippetData SnippetData
				if err := json.Unmarshal([]byte(snippet), &snippetData); err != nil {
					snippetData = SnippetData{}
				}

				if len(snippetData.Description) == 0 {
					continue
				}

				out <- SnippetArticle{
					ID:         id,
					Keyword:    keyword,
					Slug:       slug,
					Images:     images,
					Snippet:    snippetData,
					RawSnippet: snippet,
					CreatedAt:  createdAt,
				}
			}
			rows.Close()

			if !fetched {
				break
			}
		}

		db.Close()
	}

	errChan <- nil
}

func parseTime(t string) time.Time {
	for _, layout := range []string{
		"2006-01-02 15:04:05",
		"2006-01-02T15:04:05Z",
		"2006-01-02",
	} {
		if parsed, err := time.Parse(layout, t); err == nil {
			return parsed
		}
	}
	return time.Now()
}
