-- Migration 000006: Quest system — towns, NPCs, quests, hero quest tracking.

-- ============================================================
-- Towns: fixed settlements along the hero's travel road.
-- ============================================================
CREATE TABLE IF NOT EXISTS towns (
    id          BIGSERIAL PRIMARY KEY,
    name        TEXT NOT NULL UNIQUE,
    biome       TEXT NOT NULL,
    world_x     DOUBLE PRECISION NOT NULL,
    world_y     DOUBLE PRECISION NOT NULL,
    radius      DOUBLE PRECISION NOT NULL DEFAULT 8.0,
    level_min   INT NOT NULL DEFAULT 1,
    level_max   INT NOT NULL DEFAULT 100,
    created_at  TIMESTAMPTZ NOT NULL DEFAULT now()
);

-- ============================================================
-- NPCs: non-hostile characters in towns.
-- ============================================================
CREATE TABLE IF NOT EXISTS npcs (
    id          BIGSERIAL PRIMARY KEY,
    town_id     BIGINT NOT NULL REFERENCES towns(id) ON DELETE CASCADE,
    name        TEXT NOT NULL,
    type        TEXT NOT NULL CHECK (type IN ('quest_giver', 'merchant', 'healer')),
    offset_x    DOUBLE PRECISION NOT NULL DEFAULT 0,
    offset_y    DOUBLE PRECISION NOT NULL DEFAULT 0,
    created_at  TIMESTAMPTZ NOT NULL DEFAULT now()
);

CREATE INDEX IF NOT EXISTS idx_npcs_town ON npcs(town_id);

-- ============================================================
-- Quests: template definitions offered by quest-giver NPCs.
-- ============================================================
CREATE TABLE IF NOT EXISTS quests (
    id                  BIGSERIAL PRIMARY KEY,
    npc_id              BIGINT NOT NULL REFERENCES npcs(id) ON DELETE CASCADE,
    title               TEXT NOT NULL,
    description         TEXT NOT NULL DEFAULT '',
    type                TEXT NOT NULL CHECK (type IN ('kill_count', 'visit_town', 'collect_item')),
    target_count        INT NOT NULL DEFAULT 1,
    target_enemy_type   TEXT,            -- NULL = any enemy (for kill_count)
    target_town_id      BIGINT REFERENCES towns(id),  -- for visit_town quests
    drop_chance         DOUBLE PRECISION NOT NULL DEFAULT 0.3,  -- for collect_item
    min_level           INT NOT NULL DEFAULT 1,
    max_level           INT NOT NULL DEFAULT 100,
    reward_xp           BIGINT NOT NULL DEFAULT 0,
    reward_gold         BIGINT NOT NULL DEFAULT 0,
    reward_potions      INT NOT NULL DEFAULT 0,
    created_at          TIMESTAMPTZ NOT NULL DEFAULT now()
);

CREATE INDEX IF NOT EXISTS idx_quests_npc ON quests(npc_id);

-- ============================================================
-- Hero quests: per-hero progress tracking.
-- ============================================================
CREATE TABLE IF NOT EXISTS hero_quests (
    id           BIGSERIAL PRIMARY KEY,
    hero_id      BIGINT NOT NULL REFERENCES heroes(id) ON DELETE CASCADE,
    quest_id     BIGINT NOT NULL REFERENCES quests(id) ON DELETE CASCADE,
    status       TEXT NOT NULL DEFAULT 'accepted'
                 CHECK (status IN ('accepted', 'completed', 'claimed')),
    progress     INT NOT NULL DEFAULT 0,
    accepted_at  TIMESTAMPTZ NOT NULL DEFAULT now(),
    completed_at TIMESTAMPTZ,
    claimed_at   TIMESTAMPTZ,
    UNIQUE (hero_id, quest_id)
);

CREATE INDEX IF NOT EXISTS idx_hero_quests_hero ON hero_quests(hero_id);
CREATE INDEX IF NOT EXISTS idx_hero_quests_status ON hero_quests(hero_id, status);

-- ============================================================
-- Seed data: towns (idempotent — DB may already have these names)
-- ============================================================
INSERT INTO towns (name, biome, world_x, world_y, radius, level_min, level_max) VALUES
    ('Willowdale', 'meadow',   50,   15,  8.0,  1,  5),
    ('Thornwatch', 'forest',   200,  60,  8.0,  5,  10),
    ('Ashengard',  'ruins',    400,  120, 8.0,  10, 16),
    ('Redcliff',   'canyon',   650,  195, 8.0,  16, 22),
    ('Boghollow',  'swamp',    900,  270, 8.0,  22, 28),
    ('Cinderkeep', 'volcanic', 1200, 360, 8.0,  28, 34),
    ('Starfall',   'astral',   1550, 465, 8.0,  34, 40)
ON CONFLICT (name) DO NOTHING;

-- ============================================================
-- Seed data: NPCs (2-3 per town; resolve town_id by name)
-- ============================================================
INSERT INTO npcs (town_id, name, type, offset_x, offset_y)
SELECT t.id, v.npc_name, v.npc_type, v.ox, v.oy
FROM (VALUES
    ('Willowdale', 'Elder Maren',       'quest_giver', -2.0::double precision,  1.0::double precision),
    ('Willowdale', 'Peddler Finn',      'merchant',     3.0,  0.0),
    ('Willowdale', 'Sister Asha',       'healer',       0.0, -2.5),
    ('Thornwatch', 'Guard Halric',      'quest_giver', -3.0,  0.5),
    ('Thornwatch', 'Trader Wynn',       'merchant',     2.0,  2.0),
    ('Ashengard',  'Scholar Orin',      'quest_giver',  1.0, -2.0),
    ('Ashengard',  'Bone Merchant',     'merchant',    -2.0,  3.0),
    ('Ashengard',  'Priestess Liora',   'healer',       3.0,  1.0),
    ('Redcliff',   'Foreman Brak',      'quest_giver', -1.0,  2.0),
    ('Redcliff',   'Miner Supplies',    'merchant',     2.5, -1.0),
    ('Boghollow',  'Witch Nessa',       'quest_giver',  0.0,  3.0),
    ('Boghollow',  'Swamp Trader',      'merchant',    -3.0, -1.0),
    ('Boghollow',  'Marsh Healer Ren',  'healer',       2.0,  0.0),
    ('Cinderkeep', 'Forge-master Kael', 'quest_giver', -2.5,  0.0),
    ('Cinderkeep', 'Ember Merchant',    'merchant',     1.0,  2.5),
    ('Starfall',   'Seer Aelith',       'quest_giver',  0.0, -3.0),
    ('Starfall',   'Void Trader',       'merchant',     3.0,  1.0),
    ('Starfall',   'Astral Mender',     'healer',      -2.0,  2.0)
) AS v(town_name, npc_name, npc_type, ox, oy)
JOIN towns t ON t.name = v.town_name
WHERE NOT EXISTS (
    SELECT 1 FROM npcs n WHERE n.town_id = t.id AND n.name = v.npc_name
);

-- ============================================================
-- Seed data: quests (resolve npc_id / target_town_id by name; skip duplicates)
-- ============================================================

-- Willowdale — Elder Maren
INSERT INTO quests (npc_id, title, description, type, target_count, target_enemy_type, target_town_id, drop_chance, min_level, max_level, reward_xp, reward_gold, reward_potions)
SELECT n.id, s.title, s.description, s.qtype, s.target_count, s.target_enemy_type, s.target_town_id, s.drop_chance, s.min_level, s.max_level, s.reward_xp, s.reward_gold, s.reward_potions
FROM npcs n
JOIN towns t ON t.id = n.town_id
CROSS JOIN (VALUES
    ('Wolf Cull',
        'The wolves near Willowdale are getting bolder. Thin their numbers.',
        'kill_count', 5, 'wolf'::text, NULL::bigint, 0.0::double precision, 1, 5, 30::bigint, 15::bigint, 0),
    ('Boar Hunt',
        'Wild boars are trampling the crops. Take care of them.',
        'kill_count', 8, 'boar', NULL, 0.0, 2, 6, 50::bigint, 25::bigint, 1),
    ('Deliver to Thornwatch',
        'Carry this supply manifest to Guard Halric in Thornwatch.',
        'visit_town', 1, NULL, (SELECT id FROM towns WHERE name = 'Thornwatch' LIMIT 1), 0.0, 1, 10, 40::bigint, 20::bigint, 0)
) AS s(title, description, qtype, target_count, target_enemy_type, target_town_id, drop_chance, min_level, max_level, reward_xp, reward_gold, reward_potions)
WHERE t.name = 'Willowdale' AND n.name = 'Elder Maren'
  AND NOT EXISTS (SELECT 1 FROM quests q WHERE q.npc_id = n.id AND q.title = s.title);

-- Thornwatch — Guard Halric
INSERT INTO quests (npc_id, title, description, type, target_count, target_enemy_type, target_town_id, drop_chance, min_level, max_level, reward_xp, reward_gold, reward_potions)
SELECT n.id, s.title, s.description, s.qtype, s.target_count, s.target_enemy_type, s.target_town_id, s.drop_chance, s.min_level, s.max_level, s.reward_xp, s.reward_gold, s.reward_potions
FROM npcs n
JOIN towns t ON t.id = n.town_id
CROSS JOIN (VALUES
    ('Spider Infestation',
        'Cave spiders have overrun the logging trails. Clear them out.',
        'kill_count', 12, 'spider'::text, NULL::bigint, 0.0::double precision, 5, 10, 80::bigint, 40::bigint, 1),
    ('Spider Fang Collection',
        'We need spider fangs for antivenom. Collect them from slain spiders.',
        'collect_item', 5, 'spider', NULL, 0.3, 5, 10, 100::bigint, 60::bigint, 1),
    ('Forest Patrol',
        'Slay any 15 creatures along the forest road to keep it safe.',
        'kill_count', 15, NULL::text, NULL::bigint, 0.0, 5, 12, 120::bigint, 70::bigint, 1)
) AS s(title, description, qtype, target_count, target_enemy_type, target_town_id, drop_chance, min_level, max_level, reward_xp, reward_gold, reward_potions)
WHERE t.name = 'Thornwatch' AND n.name = 'Guard Halric'
  AND NOT EXISTS (SELECT 1 FROM quests q WHERE q.npc_id = n.id AND q.title = s.title);

-- Ashengard — Scholar Orin
INSERT INTO quests (npc_id, title, description, type, target_count, target_enemy_type, target_town_id, drop_chance, min_level, max_level, reward_xp, reward_gold, reward_potions)
SELECT n.id, s.title, s.description, s.qtype, s.target_count, s.target_enemy_type, s.target_town_id, s.drop_chance, s.min_level, s.max_level, s.reward_xp, s.reward_gold, s.reward_potions
FROM npcs n
JOIN towns t ON t.id = n.town_id
CROSS JOIN (VALUES
    ('Undead Purge',
        'The ruins are crawling with undead. Destroy the zombies.',
        'kill_count', 15, 'zombie'::text, NULL::bigint, 0.0::double precision, 10, 16, 150::bigint, 80::bigint, 1),
    ('Ancient Relics',
        'Search fallen enemies for fragments of the old kingdom.',
        'collect_item', 8, NULL::text, NULL::bigint, 0.25, 10, 16, 200::bigint, 120::bigint, 2),
    ('Report to Redcliff',
        'Warn Foreman Brak about the growing undead threat.',
        'visit_town', 1, NULL::text, (SELECT id FROM towns WHERE name = 'Redcliff' LIMIT 1), 0.0, 10, 20, 120::bigint, 60::bigint, 0)
) AS s(title, description, qtype, target_count, target_enemy_type, target_town_id, drop_chance, min_level, max_level, reward_xp, reward_gold, reward_potions)
WHERE t.name = 'Ashengard' AND n.name = 'Scholar Orin'
  AND NOT EXISTS (SELECT 1 FROM quests q WHERE q.npc_id = n.id AND q.title = s.title);

-- Redcliff — Foreman Brak
INSERT INTO quests (npc_id, title, description, type, target_count, target_enemy_type, target_town_id, drop_chance, min_level, max_level, reward_xp, reward_gold, reward_potions)
SELECT n.id, s.title, s.description, s.qtype, s.target_count, s.target_enemy_type, s.target_town_id, s.drop_chance, s.min_level, s.max_level, s.reward_xp, s.reward_gold, s.reward_potions
FROM npcs n
JOIN towns t ON t.id = n.town_id
CROSS JOIN (VALUES
    ('Orc Raider Cleanup',
        'Orc warriors are raiding the mine carts. Stop them.',
        'kill_count', 20, 'orc'::text, NULL::bigint, 0.0::double precision, 16, 22, 250::bigint, 150::bigint, 2),
    ('Ore Samples',
        'Collect glowing ore fragments from defeated enemies near the canyon.',
        'collect_item', 6, NULL::text, NULL::bigint, 0.3, 16, 22, 200::bigint, 120::bigint, 1)
) AS s(title, description, qtype, target_count, target_enemy_type, target_town_id, drop_chance, min_level, max_level, reward_xp, reward_gold, reward_potions)
WHERE t.name = 'Redcliff' AND n.name = 'Foreman Brak'
  AND NOT EXISTS (SELECT 1 FROM quests q WHERE q.npc_id = n.id AND q.title = s.title);

-- Boghollow — Witch Nessa
INSERT INTO quests (npc_id, title, description, type, target_count, target_enemy_type, target_town_id, drop_chance, min_level, max_level, reward_xp, reward_gold, reward_potions)
SELECT n.id, s.title, s.description, s.qtype, s.target_count, s.target_enemy_type, s.target_town_id, s.drop_chance, s.min_level, s.max_level, s.reward_xp, s.reward_gold, s.reward_potions
FROM npcs n
JOIN towns t ON t.id = n.town_id
CROSS JOIN (VALUES
    ('Swamp Creatures',
        'The swamp beasts grow more aggressive by the day. Cull 25.',
        'kill_count', 25, NULL::text, NULL::bigint, 0.0::double precision, 22, 28, 350::bigint, 200::bigint, 2),
    ('Venomous Harvest',
        'Collect venom sacs from swamp creatures for my brews.',
        'collect_item', 10, NULL::text, NULL::bigint, 0.25, 22, 28, 400::bigint, 250::bigint, 2),
    ('Message to Cinderkeep',
        'The forgemaster needs to know about the corruption spreading here.',
        'visit_town', 1, NULL::text, (SELECT id FROM towns WHERE name = 'Cinderkeep' LIMIT 1), 0.0, 22, 34, 200::bigint, 100::bigint, 1)
) AS s(title, description, qtype, target_count, target_enemy_type, target_town_id, drop_chance, min_level, max_level, reward_xp, reward_gold, reward_potions)
WHERE t.name = 'Boghollow' AND n.name = 'Witch Nessa'
  AND NOT EXISTS (SELECT 1 FROM quests q WHERE q.npc_id = n.id AND q.title = s.title);

-- Cinderkeep — Forge-master Kael
INSERT INTO quests (npc_id, title, description, type, target_count, target_enemy_type, target_town_id, drop_chance, min_level, max_level, reward_xp, reward_gold, reward_potions)
SELECT n.id, s.title, s.description, s.qtype, s.target_count, s.target_enemy_type, s.target_town_id, s.drop_chance, s.min_level, s.max_level, s.reward_xp, s.reward_gold, s.reward_potions
FROM npcs n
JOIN towns t ON t.id = n.town_id
CROSS JOIN (VALUES
    ('Demon Slayer',
        'Fire demons are emerging from the vents. Destroy them.',
        'kill_count', 10, 'fire_demon'::text, NULL::bigint, 0.0::double precision, 28, 34, 500::bigint, 300::bigint, 2),
    ('Infernal Cores',
        'Retrieve smoldering cores from defeated fire demons.',
        'collect_item', 5, 'fire_demon'::text, NULL::bigint, 0.3::double precision, 28, 34, 600::bigint, 350::bigint, 3)
) AS s(title, description, qtype, target_count, target_enemy_type, target_town_id, drop_chance, min_level, max_level, reward_xp, reward_gold, reward_potions)
WHERE t.name = 'Cinderkeep' AND n.name = 'Forge-master Kael'
  AND NOT EXISTS (SELECT 1 FROM quests q WHERE q.npc_id = n.id AND q.title = s.title);

-- Starfall — Seer Aelith
INSERT INTO quests (npc_id, title, description, type, target_count, target_enemy_type, target_town_id, drop_chance, min_level, max_level, reward_xp, reward_gold, reward_potions)
SELECT n.id, s.title, s.description, s.qtype, s.target_count, s.target_enemy_type, s.target_town_id, s.drop_chance, s.min_level, s.max_level, s.reward_xp, s.reward_gold, s.reward_potions
FROM npcs n
JOIN towns t ON t.id = n.town_id
CROSS JOIN (VALUES
    ('Titan''s Challenge',
        'The Lightning Titans must be stopped before they breach the gate.',
        'kill_count', 8, 'lightning_titan'::text, NULL::bigint, 0.0::double precision, 34, 40, 800::bigint, 500::bigint, 3),
    ('Void Fragments',
        'Gather crystallized void energy from the astral enemies.',
        'collect_item', 8, NULL::text, NULL::bigint, 0.2, 34, 40, 1000::bigint, 600::bigint, 3),
    ('Full Circle',
        'Return to Willowdale and tell Elder Maren of your journey.',
        'visit_town', 1, NULL::text, (SELECT id FROM towns WHERE name = 'Willowdale' LIMIT 1), 0.0, 34, 40, 500::bigint, 300::bigint, 2)
) AS s(title, description, qtype, target_count, target_enemy_type, target_town_id, drop_chance, min_level, max_level, reward_xp, reward_gold, reward_potions)
WHERE t.name = 'Starfall' AND n.name = 'Seer Aelith'
  AND NOT EXISTS (SELECT 1 FROM quests q WHERE q.npc_id = n.id AND q.title = s.title);
