package main

import (
	"context"
	"crypto/sha256"
	"encoding/hex"
	"encoding/json"
	"flag"
	"fmt"
	"github.com/carlosframework/docs/internal/core"
	"github.com/carlosframework/docs/internal/docs"
	"io"
	"log/slog"
	"os"
)

func must(e error) {
	if e != nil {
		panic(e)
	}
}
func main() {
	path := flag.String("db", "", "disposable database")
	address := flag.String("address", "", "synthetic local account")
	phase := flag.String("phase", "", "phase")
	flag.Parse()
	ctx := context.Background()
	app, e := docs.New(docs.Config{DBPath: *path, Env: "development", Origin: "https://compat.example", SampleDocuments: "false", Logger: slog.New(slog.NewTextHandler(io.Discard, nil))})
	must(e)
	defer app.Close()
	d, e := openProbeDB(*path)
	must(e)
	defer d.Close()
	id, e := app.Store().EnsurePerson(ctx, *address)
	must(e)
	principal := principalStep(ctx, d, *phase)
	if principal > 0 {
		var n int
		must(d.Writer().QueryRow("SELECT COUNT(*) FROM documents WHERE owner_id=?", principal).Scan(&n))
		if n == 0 {
			_, e := app.Store().Create(ctx, principal, "home-owned")
			must(e)
		}
	}
	var sqid string
	e = d.Writer().QueryRow(`SELECT sqid FROM documents WHERE title='kept-content'`).Scan(&sqid)
	if e != nil {
		doc, e := app.Store().Create(ctx, id, "kept-content")
		must(e)
		sqid = doc.Sqid
		update, e := os.ReadFile("fixtures/vectors/fragment/hello.update.bin")
		must(e)
		_, e = app.Store().ApplyUpdate(ctx, doc, fixtureActor(id, *address), update)
		must(e)
		must(app.Store().Grant(ctx, id, sqid, "reader@example.invalid", docs.RoleWriter))
		_, e = d.Writer().Exec(`INSERT INTO doc_snapshots(doc_id,seq,state,abi_version,created_at)VALUES(?,1,?,?,CURRENT_TIMESTAMP)`, doc.ID, update, core.ABIVersion)
		must(e)
		_, e = d.Writer().Exec(`INSERT INTO documents(sqid,title,guid,client_id,created_at,updated_at,owner_id)VALUES('orphan','orphan','orphan',1,CURRENT_TIMESTAMP,CURRENT_TIMESTAMP,0)`)
		must(e)
		_, e = d.Writer().Exec(`INSERT INTO grants(doc_id,subject,role,created_by)VALUES(0,'sentinel@example.invalid','reader',0)`)
		must(e)
	}
	var owner int64
	must(d.Writer().QueryRow(`SELECT owner_id FROM documents WHERE sqid=?`, sqid).Scan(&owner))
	doc, e := app.Store().Get(ctx, owner, sqid)
	must(e)
	text, e := app.Store().Text(ctx, doc)
	must(e)
	if text != "hello world" {
		panic(text)
	}
	if _, e = d.Writer().Exec(`UPDATE documents SET owner_id=owner_id`); e != nil {
		panic(e)
	}
	if _, e = d.Writer().Exec(`UPDATE grants SET created_by=created_by`); e != nil {
		panic(e)
	}
	rows, e := d.Writer().Query(`SELECT update_bin,content_encoding FROM doc_updates WHERE doc_id=(SELECT id FROM documents WHERE title='kept-content') UNION ALL SELECT state,content_encoding FROM doc_snapshots WHERE doc_id=(SELECT id FROM documents WHERE title='kept-content')`)
	must(e)
	h := sha256.New()
	encodings := []int{}
	for rows.Next() {
		var b []byte
		var encoding int
		must(rows.Scan(&b, &encoding))
		h.Write(b)
		encodings = append(encodings, encoding)
	}
	must(rows.Err())
	rows.Close()
	var author int64
	must(d.Writer().QueryRow(`SELECT created_by FROM grants WHERE subject='reader@example.invalid'`).Scan(&author))
	var homeCount int
	must(d.Writer().QueryRow(`SELECT COUNT(*) FROM documents WHERE owner_id>=4503599627370496`).Scan(&homeCount))
	var ledger int
	d.Writer().QueryRow(`SELECT COUNT(*) FROM docs_principals`).Scan(&ledger)
	out := map[string]any{"phase": *phase, "local_id": id, "home_id": principal, "owner": owner, "grant_author": author, "sqid": sqid, "content_hash": hex.EncodeToString(h.Sum(nil)), "encodings": encodings, "text": text, "principal_count": ledger, "home_owned": homeCount}
	b, e := json.Marshal(out)
	must(e)
	fmt.Println(string(b))
}
