CREATE DATABASE IF NOT EXISTS Petstoredb_target CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
USE Petstoredb_target;

CREATE TABLE IF NOT EXISTS storeLocation (
    storeId BIGINT AUTO_INCREMENT PRIMARY KEY,
    storeName VARCHAR(100) NOT NULL,
    address VARCHAR(255) NOT NULL,
    phone VARCHAR(20) NOT NULL,
    email VARCHAR(100) NOT NULL,
    imageUrl VARCHAR(255) NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);

CREATE TABLE IF NOT EXISTS users (
    id BIGINT AUTO_INCREMENT PRIMARY KEY,
    username VARCHAR(50) NULL UNIQUE,
    password VARCHAR(255) NULL,
    email VARCHAR(100) NULL UNIQUE,
    firstName VARCHAR(50) NOT NULL,
    lastName VARCHAR(50) NOT NULL,
    fullName VARCHAR(100) NULL,
    phone VARCHAR(20) NULL,
    avatarUrl VARCHAR(255) NULL,
    role VARCHAR(20) NOT NULL,
    staffRole VARCHAR(50) NULL,
    primaryStoreId BIGINT NULL,
    loyaltyPoints INT NOT NULL DEFAULT 0,
    active BOOLEAN NOT NULL DEFAULT TRUE,
    tokenVersion INT NOT NULL DEFAULT 0,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    CONSTRAINT fk_users_primary_store FOREIGN KEY (primaryStoreId) REFERENCES storeLocation(storeId) ON DELETE SET NULL
);

CREATE TABLE IF NOT EXISTS supplier (
    supId BIGINT AUTO_INCREMENT PRIMARY KEY,
    supCompany VARCHAR(100) NOT NULL,
    supContactFirstName VARCHAR(50) NOT NULL,
    supContactLastName VARCHAR(50) NOT NULL,
    supEmail VARCHAR(100) NOT NULL,
    supPhone VARCHAR(20) NOT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);

CREATE TABLE IF NOT EXISTS category (
    categoryId BIGINT AUTO_INCREMENT PRIMARY KEY,
    categoryName VARCHAR(100) NOT NULL,
    categoryType VARCHAR(50) NOT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    CONSTRAINT uq_category_name_type UNIQUE (categoryName, categoryType)
);

CREATE TABLE IF NOT EXISTS service (
    serviceId BIGINT AUTO_INCREMENT PRIMARY KEY,
    serviceName VARCHAR(100) NOT NULL,
    serviceDesc TEXT NULL,
    serviceDuration INT NOT NULL,
    servicePrice DECIMAL(10, 2) NOT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);

CREATE TABLE IF NOT EXISTS service_species (
    serviceId BIGINT NOT NULL,
    species VARCHAR(50) NOT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    PRIMARY KEY (serviceId, species),
    CONSTRAINT fk_service_species_service FOREIGN KEY (serviceId) REFERENCES service(serviceId) ON DELETE CASCADE
);

CREATE TABLE IF NOT EXISTS product (
    prodId BIGINT AUTO_INCREMENT PRIMARY KEY,
    prodName VARCHAR(100) NOT NULL,
    prodPrice DECIMAL(10, 2) NOT NULL,
    categoryId BIGINT NOT NULL,
    prodDesc TEXT NULL,
    imageUrl VARCHAR(255) NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    CONSTRAINT fk_product_category FOREIGN KEY (categoryId) REFERENCES category(categoryId)
);

CREATE TABLE IF NOT EXISTS inventory (
    inventoryId BIGINT AUTO_INCREMENT PRIMARY KEY,
    storeId BIGINT NOT NULL,
    prodId BIGINT NOT NULL,
    quantity INT NOT NULL DEFAULT 0,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    CONSTRAINT uq_inventory_store_product UNIQUE (storeId, prodId),
    CONSTRAINT fk_inventory_store FOREIGN KEY (storeId) REFERENCES storeLocation(storeId),
    CONSTRAINT fk_inventory_product FOREIGN KEY (prodId) REFERENCES product(prodId)
);

CREATE TABLE IF NOT EXISTS productSupplier (
    supId BIGINT NOT NULL,
    prodId BIGINT NOT NULL,
    cost DECIMAL(10, 2) NOT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    PRIMARY KEY (supId, prodId),
    CONSTRAINT fk_product_supplier_supplier FOREIGN KEY (supId) REFERENCES supplier(supId),
    CONSTRAINT fk_product_supplier_product FOREIGN KEY (prodId) REFERENCES product(prodId)
);

CREATE TABLE IF NOT EXISTS purchaseOrder (
    purchaseOrderId BIGINT AUTO_INCREMENT PRIMARY KEY,
    supId BIGINT NOT NULL,
    storeId BIGINT NOT NULL,
    orderDate DATE NOT NULL,
    status VARCHAR(50) NOT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    CONSTRAINT fk_purchase_order_supplier FOREIGN KEY (supId) REFERENCES supplier(supId),
    CONSTRAINT fk_purchase_order_store FOREIGN KEY (storeId) REFERENCES storeLocation(storeId)
);

CREATE TABLE IF NOT EXISTS coupon (
    couponId BIGINT AUTO_INCREMENT PRIMARY KEY,
    couponCode VARCHAR(50) NOT NULL,
    discountType VARCHAR(20) NOT NULL,
    discountValue DECIMAL(10, 2) NOT NULL,
    minOrderAmount DECIMAL(10, 2) NULL,
    active BOOLEAN NOT NULL DEFAULT TRUE,
    startsAt DATETIME NULL,
    endsAt DATETIME NULL,
    usageLimit INT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    CONSTRAINT uq_coupon_code UNIQUE (couponCode)
);

CREATE TABLE IF NOT EXISTS pet (
    petId BIGINT AUTO_INCREMENT PRIMARY KEY,
    petName VARCHAR(50) NOT NULL,
    petSpecies VARCHAR(50) NOT NULL,
    petBreed VARCHAR(50) NULL,
    petAge INT NULL,
    petStatus VARCHAR(20) NOT NULL,
    petPrice DECIMAL(10, 2) NULL,
    imageUrl VARCHAR(255) NULL,
    ownerUserId BIGINT NULL,
    storeId BIGINT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    CONSTRAINT fk_pet_owner_user FOREIGN KEY (ownerUserId) REFERENCES users(id) ON DELETE SET NULL,
    CONSTRAINT fk_pet_store FOREIGN KEY (storeId) REFERENCES storeLocation(storeId) ON DELETE SET NULL
);

CREATE TABLE IF NOT EXISTS appointment (
    appointmentId BIGINT AUTO_INCREMENT PRIMARY KEY,
    serviceId BIGINT NOT NULL,
    petId BIGINT NOT NULL,
    customerId BIGINT NOT NULL,
    storeId BIGINT NOT NULL,
    employeeId BIGINT NOT NULL,
    appointmentDate DATE NOT NULL,
    appointmentTime TIME NOT NULL,
    appointmentStatus VARCHAR(20) NOT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    CONSTRAINT fk_appointment_service FOREIGN KEY (serviceId) REFERENCES service(serviceId),
    CONSTRAINT fk_appointment_pet FOREIGN KEY (petId) REFERENCES pet(petId),
    CONSTRAINT fk_appointment_customer FOREIGN KEY (customerId) REFERENCES users(id),
    CONSTRAINT fk_appointment_store FOREIGN KEY (storeId) REFERENCES storeLocation(storeId),
    CONSTRAINT fk_appointment_employee FOREIGN KEY (employeeId) REFERENCES users(id)
);

CREATE TABLE IF NOT EXISTS adoption (
    adoptionId BIGINT AUTO_INCREMENT PRIMARY KEY,
    petId BIGINT NOT NULL,
    customerId BIGINT NOT NULL,
    employeeId BIGINT NOT NULL,
    sourceStoreId BIGINT NOT NULL,
    adoptionDate DATE NOT NULL,
    adoptionStatus VARCHAR(20) NOT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    CONSTRAINT fk_adoption_pet FOREIGN KEY (petId) REFERENCES pet(petId),
    CONSTRAINT fk_adoption_customer FOREIGN KEY (customerId) REFERENCES users(id),
    CONSTRAINT fk_adoption_employee FOREIGN KEY (employeeId) REFERENCES users(id),
    CONSTRAINT fk_adoption_source_store FOREIGN KEY (sourceStoreId) REFERENCES storeLocation(storeId)
);

CREATE TABLE IF NOT EXISTS cart (
    cartId BIGINT AUTO_INCREMENT PRIMARY KEY,
    userId BIGINT NOT NULL,
    storeId BIGINT NULL,
    couponId BIGINT NULL,
    cartStatus VARCHAR(20) NOT NULL DEFAULT 'ACTIVE',
    subtotalAmount DECIMAL(10, 2) NOT NULL DEFAULT 0.00,
    discountAmount DECIMAL(10, 2) NOT NULL DEFAULT 0.00,
    totalAmount DECIMAL(10, 2) NOT NULL DEFAULT 0.00,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    CONSTRAINT fk_cart_user FOREIGN KEY (userId) REFERENCES users(id),
    CONSTRAINT fk_cart_store FOREIGN KEY (storeId) REFERENCES storeLocation(storeId) ON DELETE SET NULL,
    CONSTRAINT fk_cart_coupon FOREIGN KEY (couponId) REFERENCES coupon(couponId) ON DELETE SET NULL
);

CREATE TABLE IF NOT EXISTS cart_item (
    cartItemId BIGINT AUTO_INCREMENT PRIMARY KEY,
    cartId BIGINT NOT NULL,
    prodId BIGINT NOT NULL,
    quantity INT NOT NULL,
    unitPrice DECIMAL(10, 2) NOT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    CONSTRAINT fk_cart_item_cart FOREIGN KEY (cartId) REFERENCES cart(cartId) ON DELETE CASCADE,
    CONSTRAINT fk_cart_item_product FOREIGN KEY (prodId) REFERENCES product(prodId)
);

CREATE TABLE IF NOT EXISTS sale (
    saleId BIGINT AUTO_INCREMENT PRIMARY KEY,
    saleDate DATETIME NOT NULL,
    totalAmount DECIMAL(10, 2) NOT NULL,
    paymentMethod VARCHAR(50) NOT NULL,
    employeeId BIGINT NOT NULL,
    storeId BIGINT NOT NULL,
    customerId BIGINT NULL,
    isRefund BOOLEAN NOT NULL DEFAULT FALSE,
    originalSaleId BIGINT NULL,
    channel VARCHAR(20) NOT NULL DEFAULT 'IN_STORE',
    cartId BIGINT NULL,
    couponId BIGINT NULL,
    subtotalAmount DECIMAL(10, 2) NULL,
    couponDiscountAmount DECIMAL(10, 2) NOT NULL DEFAULT 0.00,
    employeeDiscountAmount DECIMAL(10, 2) NOT NULL DEFAULT 0.00,
    pointsEarned INT NOT NULL DEFAULT 0,
    pointsUsed INT NOT NULL DEFAULT 0,
    pointsDiscountAmount DECIMAL(10, 2) NOT NULL DEFAULT 0.00,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    CONSTRAINT fk_sale_employee FOREIGN KEY (employeeId) REFERENCES users(id),
    CONSTRAINT fk_sale_store FOREIGN KEY (storeId) REFERENCES storeLocation(storeId),
    CONSTRAINT fk_sale_customer FOREIGN KEY (customerId) REFERENCES users(id) ON DELETE SET NULL,
    CONSTRAINT fk_sale_original_sale FOREIGN KEY (originalSaleId) REFERENCES sale(saleId),
    CONSTRAINT fk_sale_cart FOREIGN KEY (cartId) REFERENCES cart(cartId) ON DELETE SET NULL,
    CONSTRAINT fk_sale_coupon FOREIGN KEY (couponId) REFERENCES coupon(couponId) ON DELETE SET NULL
);

CREATE TABLE IF NOT EXISTS saleItem (
    saleItemId BIGINT AUTO_INCREMENT PRIMARY KEY,
    saleId BIGINT NOT NULL,
    prodId BIGINT NOT NULL,
    quantity INT NOT NULL,
    unitPrice DECIMAL(10, 2) NOT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    CONSTRAINT fk_sale_item_sale FOREIGN KEY (saleId) REFERENCES sale(saleId) ON DELETE CASCADE,
    CONSTRAINT fk_sale_item_product FOREIGN KEY (prodId) REFERENCES product(prodId)
);

CREATE TABLE IF NOT EXISTS refund (
    id BIGINT AUTO_INCREMENT PRIMARY KEY,
    saleId BIGINT NOT NULL,
    customerId BIGINT NOT NULL,
    amount DECIMAL(10, 2) NOT NULL,
    reason VARCHAR(500) NOT NULL,
    status VARCHAR(20) NOT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    CONSTRAINT fk_refund_sale FOREIGN KEY (saleId) REFERENCES sale(saleId),
    CONSTRAINT fk_refund_customer FOREIGN KEY (customerId) REFERENCES users(id)
);

CREATE TABLE IF NOT EXISTS refund_item (
    id BIGINT AUTO_INCREMENT PRIMARY KEY,
    refund_id BIGINT NOT NULL,
    prod_id BIGINT NOT NULL,
    quantity INT NOT NULL,
    unit_price DECIMAL(10, 2) NOT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    CONSTRAINT fk_refund_item_refund FOREIGN KEY (refund_id) REFERENCES refund(id) ON DELETE CASCADE,
    CONSTRAINT fk_refund_item_product FOREIGN KEY (prod_id) REFERENCES product(prodId)
);

CREATE TABLE IF NOT EXISTS conversation (
    id BIGINT AUTO_INCREMENT PRIMARY KEY,
    customerId BIGINT NOT NULL,
    staffId BIGINT NULL,
    status VARCHAR(20) NOT NULL DEFAULT 'OPEN',
    mode VARCHAR(20) NOT NULL DEFAULT 'AUTOMATED',
    humanRequestedAt TIMESTAMP NULL,
    created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    CONSTRAINT fk_conversation_customer FOREIGN KEY (customerId) REFERENCES users(id),
    CONSTRAINT fk_conversation_staff FOREIGN KEY (staffId) REFERENCES users(id) ON DELETE SET NULL
);

CREATE TABLE IF NOT EXISTS message (
    id BIGINT AUTO_INCREMENT PRIMARY KEY,
    conversationId BIGINT NOT NULL,
    senderId BIGINT NOT NULL,
    content TEXT NULL,
    attachmentUrl VARCHAR(255) NULL,
    attachmentName VARCHAR(255) NULL,
    attachmentMimeType VARCHAR(100) NULL,
    attachmentSizeBytes BIGINT NULL,
    timestamp TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    isRead BOOLEAN NOT NULL DEFAULT FALSE,
    CONSTRAINT fk_message_conversation FOREIGN KEY (conversationId) REFERENCES conversation(id) ON DELETE CASCADE,
    CONSTRAINT fk_message_sender FOREIGN KEY (senderId) REFERENCES users(id)
);

CREATE TABLE IF NOT EXISTS activityLog (
    logId BIGINT AUTO_INCREMENT PRIMARY KEY,
    userId BIGINT NOT NULL,
    storeId BIGINT NULL,
    usernameSnapshot VARCHAR(50) NULL,
    fullNameSnapshot VARCHAR(100) NULL,
    roleSnapshot VARCHAR(20) NULL,
    storeNameSnapshot VARCHAR(100) NULL,
    activity TEXT NOT NULL,
    logTimestamp TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    CONSTRAINT fk_activity_log_user FOREIGN KEY (userId) REFERENCES users(id),
    CONSTRAINT fk_activity_log_store FOREIGN KEY (storeId) REFERENCES storeLocation(storeId) ON DELETE SET NULL
);

CREATE INDEX idx_users_primary_store ON users(primaryStoreId);
CREATE INDEX idx_users_role ON users(role);
CREATE INDEX idx_users_name ON users(lastName, firstName);
CREATE INDEX idx_service_species_species ON service_species(species);
CREATE INDEX idx_inventory_store ON inventory(storeId);
CREATE INDEX idx_inventory_product ON inventory(prodId);
CREATE INDEX idx_purchase_order_store ON purchaseOrder(storeId);
CREATE INDEX idx_pet_owner_user ON pet(ownerUserId);
CREATE INDEX idx_pet_store ON pet(storeId);
CREATE INDEX idx_pet_species ON pet(petSpecies);
CREATE INDEX idx_pet_name ON pet(petName);
CREATE INDEX idx_appointment_store ON appointment(storeId);
CREATE INDEX idx_appointment_employee ON appointment(employeeId);
CREATE INDEX idx_appointment_customer ON appointment(customerId);
CREATE INDEX idx_appointment_pet ON appointment(petId);
CREATE INDEX idx_appointment_date_status ON appointment(appointmentDate, appointmentStatus);
CREATE INDEX idx_adoption_store ON adoption(sourceStoreId);
CREATE INDEX idx_adoption_employee ON adoption(employeeId);
CREATE INDEX idx_sale_store ON sale(storeId);
CREATE INDEX idx_sale_employee ON sale(employeeId);
CREATE INDEX idx_sale_customer ON sale(customerId);
CREATE INDEX idx_sale_date ON sale(saleDate);
CREATE INDEX idx_cart_user ON cart(userId);
CREATE INDEX idx_conversation_customer ON conversation(customerId);
CREATE INDEX idx_conversation_staff ON conversation(staffId);
CREATE INDEX idx_activity_log_store ON activityLog(storeId);
CREATE INDEX idx_activity_log_timestamp_id ON activityLog(logTimestamp, logId);
