use master
GO

DROP TABLE [kufrik]
GO

CREATE DATABASE [kufrik]
-- CONTAINMENT = NONE
-- ON  PRIMARY 
--( NAME = N'kufrik', FILENAME = N'/var/opt/mssql/data/kufrik.mdf' , SIZE = 8192KB , FILEGROWTH = 65536KB )
-- LOG ON 
--( NAME = N'kufrik_log', FILENAME = N'/var/opt/mssql/data/kufrik_log.ldf' , SIZE = 8192KB , FILEGROWTH = 65536KB )
GO
ALTER DATABASE [kufrik] SET COMPATIBILITY_LEVEL = 160
GO

--Pokud je AUTO_CLOSE zapnuté (ON), databáze se po odpojení posledního uživatele kompletně uzavře a uvolní paměť. Při dalším požadavku se pak musí znovu otevírat, což způsobuje výrazné zpoždění (latenci) prvního dotazu a zbytečnou zátěž na disk a CPU.
ALTER DATABASE [kufrik] SET AUTO_CLOSE OFF WITH NO_WAIT;
GO

--user:
USE [master]
GO
CREATE LOGIN [kufrik] WITH PASSWORD=N'giteaKufrik_2026!', DEFAULT_DATABASE=[master], CHECK_EXPIRATION=OFF, CHECK_POLICY=OFF
GO
USE [kufrik]
GO
CREATE USER [kufrik] FOR LOGIN [kufrik]
GO 
ALTER USER [kufrik] WITH DEFAULT_SCHEMA=[dbo]
GO
ALTER ROLE [db_owner] ADD MEMBER [kufrik]
GO

-- 1. PŘIHLAŠOVACÍ ÚČET (Fyzická osoba)
CREATE TABLE [dbo].[UZIVATEL] (
    [ID] [int] IDENTITY(1,1) NOT NULL,
    [EMAIL] [nvarchar](100) NOT NULL,
    [HESLO_HASH] [nvarchar](255) NOT NULL,
    [JMENO] [nvarchar](100) NULL,
    [PRIJMENI] [nvarchar](100) NULL,
    [TELEFON] [nvarchar](20) NULL,
    [POSLEDNI_PRIHLASENI] [datetime2](7) NULL,
    [AKTIVNI] [bit] NOT NULL DEFAULT 1,
    CONSTRAINT [PK_UZIVATEL] PRIMARY KEY CLUSTERED ([ID] ASC),
    CONSTRAINT [UQ_UZIVATEL_EMAIL] UNIQUE ([EMAIL])
);

ALTER TABLE [dbo].[UZIVATEL] ADD
    -- Identifikátor nebo název cílové databáze
    [DATABASE_NAME] [nvarchar](128) NULL,   
    -- Volitelně celý connection string (nebo klíč do konfigurace aplikace)
    [CONNECTION_STRING_KEY] [nvarchar](100) NULL;
GO

-- 2. FIRMA / OSVČ (Fakturační jednotka = TENANT)
CREATE TABLE [dbo].[FIRMA] (
    [ID] [int] IDENTITY(1,1) NOT NULL,
    [NAZEV] [nvarchar](255) NOT NULL, -- Jméno a příjmení OSVČ nebo název s.r.o.
    [IC] [nvarchar](8) NULL,
    [DIC] [nvarchar](12) NULL,
    [PLATCE_DPH] [bit] NOT NULL DEFAULT 1,
    
    -- Sídlo
    [ULICE] [nvarchar](100) NULL,
    [MESTO] [nvarchar](100) NULL,
    [PSC] [nvarchar](10) NULL,
    [ZEME_KOD] [nvarchar](2) NOT NULL DEFAULT 'CZ',

    -- Banka pro fakturaci
    [CISLO_UCTU] [nvarchar](30) NULL,
    [BANKA_KOD] [nvarchar](10) NULL,
    [IBAN] [nvarchar](34) NULL,
    [BIC] [nvarchar](11) NULL,

    [DATUM_VYTVORENI] [datetime2](7) NOT NULL DEFAULT SYSDATETIME(),
    CONSTRAINT [PK_FIRMA] PRIMARY KEY CLUSTERED ([ID] ASC)
);

-- 3. VAZBA UŽIVATEL <-> FIRMA (Práva k firmám)
CREATE TABLE [dbo].[UZIVATEL_FIRMA] (
    [UZIVATEL_ID] [int] NOT NULL,
    [FIRMA_ID] [int] NOT NULL,
    [ROLE] [nvarchar](20) NOT NULL DEFAULT 'OWNER', -- 'OWNER', 'ACCOUNTANT', 'READONLY'
    CONSTRAINT [PK_UZIVATEL_FIRMA] PRIMARY KEY CLUSTERED ([UZIVATEL_ID], [FIRMA_ID]),
    CONSTRAINT [FK_UF_UZIVATEL] FOREIGN KEY ([UZIVATEL_ID]) REFERENCES [dbo].[UZIVATEL] ([ID]),
    CONSTRAINT [FK_UF_FIRMA] FOREIGN KEY ([FIRMA_ID]) REFERENCES [dbo].[FIRMA] ([ID])
);
 
 -- ==========================================
-- 1. ZÁKAZNÍCI / ODBĚRATELÉ (vázaní na Firmu)
-- ==========================================
CREATE TABLE [dbo].[ZAKAZNIK](
    [ID] [int] IDENTITY(2,1) NOT NULL,
    [FIRMA_ID] [int] NOT NULL,                      -- Izolace dat (Tenant)
    [JMENO] [nvarchar](255) NULL,
    [PRIJMENI] [nvarchar](255) NOT NULL,
    [ULICE] [nvarchar](50) NULL,
    [MESTO] [nvarchar](50) NULL,
    [PSC] [nvarchar](5) NULL,
    [IC] [nvarchar](8) NULL,
    [DIC] [nvarchar](10) NULL,
    [TELEFON] [nvarchar](15) NULL,
    [EMAIL] [nvarchar](100) NULL,
    [AKTIVNI] [bit] NOT NULL CONSTRAINT [DF_ZAKAZNIK_AKTIVNI] DEFAULT ((1)),
    
    CONSTRAINT [PK_ZAKAZNIK] PRIMARY KEY CLUSTERED ([ID] ASC),
    CONSTRAINT [FK_ZAKAZNIK_FIRMA] FOREIGN KEY ([FIRMA_ID]) REFERENCES [dbo].[FIRMA] ([ID])
);
GO

CREATE NONCLUSTERED INDEX [IX_ZAKAZNIK_FIRMA_ID] ON [dbo].[ZAKAZNIK]([FIRMA_ID] ASC);
GO

-- ==========================================
-- 2. HLAVIČKA FAKTURY
-- ==========================================
CREATE TABLE [dbo].[FAKTURA](
    [ID] [int] IDENTITY(15,1) NOT NULL,
    [FIRMA_ID] [int] NOT NULL,                      -- Izolace dat (Tenant)
    [ZAKAZNIK] [int] NULL,                          -- Vazba na adresář (volitelná, pro historii)
    
    [CISLO] [nvarchar](20) NOT NULL,
    [CISLO_ABS] [int] NOT NULL,                     -- Sekvenční pořadové číslo v roce
    [FORMA_UHRADY] [tinyint] NOT NULL CONSTRAINT [DF_FAKTURA_FORMA_UHRADY] DEFAULT ((1)),
    
    [DATUM_VYSTAVENI] [date] NOT NULL,
    [DATUM_SPLATNOSTI] [date] NOT NULL,
    [DATUM_DUZP] [date] NULL,                       -- Doplněno pro DPH plnění

    -- Snapshot Dodavatele (OSVČ / Firma v čase vystavení)
    [D_PRAJM] [nvarchar](511) NULL,
    [D_ULICE] [nvarchar](50) NULL,
    [D_MESTO] [nvarchar](50) NULL,
    [D_PSC] [nvarchar](50) NULL,
    [D_IC] [nvarchar](8) NULL,
    [D_DIC] [nvarchar](10) NULL,
    [D_BANKA] [nvarchar](100) NULL,
    [D_TELEFON] [nvarchar](15) NULL,
    [D_EMAIL] [nvarchar](100) NULL,
    [D_WEB] [nvarchar](100) NULL,

    -- Snapshot Odběratele (Zákazník v čase vystavení)
    [O_PRAJM] [nvarchar](511) NULL,
    [O_ULICE] [nvarchar](50) NULL,
    [O_MESTO] [nvarchar](50) NULL,
    [O_PSC] [nvarchar](5) NULL,
    [O_IC] [nvarchar](8) NULL,
    [O_DIC] [nvarchar](10) NULL,

    [CINNOSTI] [nvarchar](max) NULL,                 -- Nahrazeno ntext -> nvarchar(max)
    [STAV] [nvarchar](20) NOT NULL CONSTRAINT [DF_FAKTURA_STAV] DEFAULT ('ISSUED'),

    CONSTRAINT [PK_FAKTURA] PRIMARY KEY CLUSTERED ([ID] ASC),
    CONSTRAINT [FK_FAKTURA_FIRMA] FOREIGN KEY ([FIRMA_ID]) REFERENCES [dbo].[FIRMA] ([ID]),
    CONSTRAINT [FK_FAKTURA_ZAKAZNIK] FOREIGN KEY ([ZAKAZNIK]) REFERENCES [dbo].[ZAKAZNIK] ([ID]),
    
    -- Číslo faktury je unikátní vždy jen v rámci jedné firmy
    CONSTRAINT [UQ_FAKTURA_FIRMA_CISLO] UNIQUE ([FIRMA_ID], [CISLO])
);
GO

CREATE NONCLUSTERED INDEX [IX_FAKTURA_FIRMA_DATUM] ON [dbo].[FAKTURA]([FIRMA_ID] ASC, [DATUM_VYSTAVENI] DESC);
GO

-- ==========================================
-- 3. POLOŽKY FAKTURY
-- ==========================================
CREATE TABLE [dbo].[POLOZKA](
    [ID] [int] IDENTITY(24,1) NOT NULL,
    [FAKTURA] [int] NOT NULL,
    [FIRMA_ID] [int] NOT NULL,                      -- Duplikováno pro rychlé filtry a RLS

    [NAZEV] [nvarchar](255) NOT NULL,
    [POCET] [float] NOT NULL DEFAULT 1,
    [JEDNOTKA] [nvarchar](10) NULL DEFAULT 'ks',
    [CENA_JEDNOTKA] [money] NOT NULL,
    [SLEVA] [real] NULL DEFAULT 0,
    [CENA] [money] NOT NULL,                        -- Celková cena položky po slevě

    CONSTRAINT [PK_POLOZKA] PRIMARY KEY CLUSTERED ([ID] ASC),
    CONSTRAINT [FK_POLOZKA_FAKTURA] FOREIGN KEY ([FAKTURA]) REFERENCES [dbo].[FAKTURA] ([ID]) ON DELETE CASCADE,
    CONSTRAINT [FK_POLOZKA_FIRMA] FOREIGN KEY ([FIRMA_ID]) REFERENCES [dbo].[FIRMA] ([ID])
);
GO

CREATE NONCLUSTERED INDEX [IX_POLOZKA_FAKTURA] ON [dbo].[POLOZKA]([FAKTURA] ASC);
GO

-- ==========================================
-- 4. ÚHRADY / PLATBY FAKTUR
-- ==========================================
CREATE TABLE [dbo].[PLATBA](
    [ID] [int] IDENTITY(11,1) NOT NULL,
    [FAKTURA] [int] NOT NULL,
    [CASTKA] [money] NOT NULL,
    [DATUM] [datetime2](7) NOT NULL DEFAULT SYSDATETIME(),
    [POZNAMKA] [nvarchar](max) NULL,                 -- Nahrazeno ntext -> nvarchar(max)

    CONSTRAINT [PK_PLATBA] PRIMARY KEY CLUSTERED ([ID] ASC),
    CONSTRAINT [FK_PLATBA_FAKTURA] FOREIGN KEY ([FAKTURA]) REFERENCES [dbo].[FAKTURA] ([ID]) ON DELETE CASCADE
);
GO

CREATE NONCLUSTERED INDEX [IX_PLATBA_FAKTURA] ON [dbo].[PLATBA]([FAKTURA] ASC);
GO


-- ==========================================
-- 5. SECURITY
-- ==========================================

-- 1. Vytvoření schématu pro bezpečnostní objekty
CREATE SCHEMA Security;
GO

-- 2. Predikátová funkce pro kontrolu FirmaId
CREATE FUNCTION Security.fn_SecurityPredicate(@FirmaId INT)
RETURNS TABLE
WITH SCHEMABINDING
AS
RETURN SELECT 1 AS fn_SecurityPredicate_result
WHERE 
    -- Vyhodnotí se jako pravda pouze pokud se FIRMA_ID řádku shoduje se SESSION_CONTEXTu
    @FirmaId = CAST(SESSION_CONTEXT(N'FirmaId') AS INT);
GO

-- 3. Vytvoření Security Policy pro tabulky
CREATE SECURITY POLICY Security.FirmaSecurityPolicy
ADD FILTER PREDICATE Security.fn_SecurityPredicate(FIRMA_ID) ON dbo.FAKTURA,
ADD BLOCK PREDICATE Security.fn_SecurityPredicate(FIRMA_ID) ON dbo.FAKTURA,

ADD FILTER PREDICATE Security.fn_SecurityPredicate(FIRMA_ID) ON dbo.ZAKAZNIK,
ADD BLOCK PREDICATE Security.fn_SecurityPredicate(FIRMA_ID) ON dbo.ZAKAZNIK,

ADD FILTER PREDICATE Security.fn_SecurityPredicate(FIRMA_ID) ON dbo.POLOZKA,
ADD BLOCK PREDICATE Security.fn_SecurityPredicate(FIRMA_ID) ON dbo.POLOZKA
WITH (STATE = ON);
GO


-- ==========================================
-- Cvičná data a UZIVATEL
-- ==========================================

-- Vygenerovaný platný BCrypt hash (cost: 12) pro heslo: admin1234
DECLARE @HesloHash NVARCHAR(255) = N'$2y$12$9SAWctZKp/JpYl7K.awSRehXOXVyRpu0ofReqvbm1jVjvdz41zH7a';
DECLARE @Email NVARCHAR(100) = N'admin@kmetix.cz';

IF NOT EXISTS (SELECT 1 FROM dbo.UZIVATEL WHERE EMAIL = @Email)
BEGIN
    INSERT INTO dbo.UZIVATEL (
        [EMAIL],
        [HESLO_HASH],
        [JMENO],
        [PRIJMENI],
        [TELEFON],
        [DATABASE_NAME],
        [CONNECTION_STRING_KEY],
        [AKTIVNI]
    )
    VALUES (
        @Email,
        @HesloHash,
        N'Pavel',
        N'Kowalski',
        N'+420123456789',
        N'',  -- Cílová databáze pro klientská data
        NULL,
        1                     -- AKTIVNI = 1
    );

    PRINT 'Uživatel admin@kmetix.cz byl úspěšně vytvořen s heslem: admin1234';
END
ELSE
BEGIN
    PRINT 'Uživatel s tímto e-mailem již v databázi existuje.';
END
GO

