package aceboot::orm.tests

import aceboot::orm.common.*
import aceboot::orm.sqlite.*

import std.unittest.*
import std.unittest.testmacro.*
import aceboot::orm.macros.*

// F2 级联保存 cascade(to-one):保存父时自动持久化 owner 侧关系子对象并串好 FK。
// 独立前缀实体(f2_*)避免与既有测试实体重名(同包全局唯一)。

@Entity["f2_authors"]
public class _F2Author {
    @Id[]
    public var id: Int64 = 0
    @Column[]
    public var name: String = ""
}

@Entity["f2_books"]
public class _F2Book {
    @Id[]
    public var id: Int64 = 0
    @Column[]
    public var title: String = ""
    // cascade=true:save/insert 本书时自动持久化未存的 author 并回填 FK。
    @ManyToOne[_F2Author, "f2_authors", cascade = true]
    public var author: ?_F2Author = None
}

// 无 cascade 的对照实体:关系不带 cascade,保存父不应持久化子。
@Entity["f2_books_nc"]
public class _F2BookNC {
    @Id[]
    public var id: Int64 = 0
    @Column[]
    public var title: String = ""
    @ManyToOne[_F2Author, "f2_authors"]
    public var author: ?_F2Author = None
}

func f2Setup(): DataSource {
    let ds = DataSource(SqliteDriver(":memory:"))
    Repository<_F2Author>(ds, _F2AuthorMapper()).createTable()
    Repository<_F2Book>(ds, _F2BookMapper()).createTable()
    Repository<_F2BookNC>(ds, _F2BookNCMapper()).createTable()
    return ds
}

// save(book) 级联存未持久化的 author:author.id 被回填、book.authorId==author.id、findOne 取回 author。
@Test
func test_f2_cascade_save_to_one() {
    let ds = f2Setup()
    let bookRepo = Repository<_F2Book>(ds, _F2BookMapper())
    let authorRepo = Repository<_F2Author>(ds, _F2AuthorMapper())

    let a = _F2Author()
    a.name = "Rowling"
    let b = _F2Book()
    b.title = "HP"
    b.author = Some(a)

    let bid = bookRepo.save(b)
    @Expect(bid > 0, true)
    // 子被级联持久化,id 经引用语义回填。
    @Expect(a.id > 0, true)
    @Expect(authorRepo.count(), 1)

    // findOne 联表取回 author。
    let back = bookRepo.findOne(DbInt(bid), ["author"])
    @Expect(back.isSome(), true)
    let loaded = back.getOrThrow()
    @Expect(loaded.title, "HP")
    @Expect(loaded.author.isSome(), true)
    @Expect(loaded.author.getOrThrow().name, "Rowling")
    @Expect(loaded.author.getOrThrow().id, a.id)
    ds.driver.close()
}

// insert(book) 直调(非经 save)也触发级联。
@Test
func test_f2_cascade_insert_to_one() {
    let ds = f2Setup()
    let bookRepo = Repository<_F2Book>(ds, _F2BookMapper())
    let authorRepo = Repository<_F2Author>(ds, _F2AuthorMapper())

    let a = _F2Author()
    a.name = "Tolkien"
    let b = _F2Book()
    b.title = "LOTR"
    b.author = Some(a)

    bookRepo.insert(b)
    @Expect(a.id > 0, true)
    @Expect(authorRepo.count(), 1)

    // FK 落库正确:按 authorId 取回该书。
    let byFk = bookRepo.findBy("authorId", DbInt(a.id))
    @Expect(byFk.size, 1)
    @Expect(byFk[0].title, "LOTR")
    ds.driver.close()
}

// 默认 cascade=false:同结构但关系不带 cascade,save 父不持久化子(守卫精确)。
@Test
func test_f2_no_cascade_leaves_child_unsaved() {
    let ds = f2Setup()
    let ncRepo = Repository<_F2BookNC>(ds, _F2BookNCMapper())
    let authorRepo = Repository<_F2Author>(ds, _F2AuthorMapper())

    let a = _F2Author()
    a.name = "Ghost"
    let b = _F2BookNC()
    b.title = "NC"
    b.author = Some(a)

    ncRepo.save(b)
    // 子未被持久化:author.id 仍为 0,authors 表为空。
    @Expect(a.id, 0)
    @Expect(authorRepo.count(), 0)
    ds.driver.close()
}

// 已持久化的子(id!=0)级联时走 update 分支,不重复插入。
@Test
func test_f2_cascade_existing_child_not_duplicated() {
    let ds = f2Setup()
    let bookRepo = Repository<_F2Book>(ds, _F2BookMapper())
    let authorRepo = Repository<_F2Author>(ds, _F2AuthorMapper())

    let a = _F2Author()
    a.name = "Existing"
    authorRepo.insert(a)
    let aid = a.id
    @Expect(aid > 0, true)

    let b = _F2Book()
    b.title = "B1"
    b.author = Some(a)
    bookRepo.save(b)

    // 未新增 author 行(仍 1 条),FK 指向既有子。
    @Expect(authorRepo.count(), 1)
    @Expect(a.id, aid)
    ds.driver.close()
}